代码之家  ›  专栏  ›  技术社区  ›  Tony Tannous

如何使用uu属性uuu((可见性(“默认”)))?

  •  2
  • Tony Tannous  · 技术社区  · 6 年前

    Visibility 在gnuwiki中,这是很清楚的。

    this C++教程实例

    // classes example
    #include <iostream>
    using namespace std;
    
    class Rectangle {
        int width, height;
      public:
        void set_values (int,int);
        int area() {return width*height;}
    };
    
    void Rectangle::set_values (int x, int y) {
      width = x;
      height = y;
    }
    

    有没有可能 area() 公共和 set_values(int,int) 如第一个链接所示的本地而不改变代码?

    我写了我的makefile来获取 .so

    someproj.so : someproj.cpp
        g++ --std=c++11 -O3 -fPIC -shared someproj.cpp -o someproj.so
    

    修改为通过添加 -fvisibility=hidden

    someproj.so : someproj.cpp
        g++ --std=c++11 -O3 -fvisibility=hidden -fPIC -shared someproj.cpp -o someproj.so
    

    当前使用4.7.2版gcc

    1 回复  |  直到 6 年前
        1
  •  67
  •   keineahnung2345 Daniel Ballinger    5 年前

    是否可以通过修改上面的编译命令来定制哪些函数是公开的?

    No.编译选项 -fvisibility=[default|internal|hidden|protected] (请注意 全部的 除了 通过反补贴被明确排除在外的 __attribute__((visibility(....))) 在源代码中

    也不是。

    您更改源代码以使 Rectangle::area() 动态 可见,而所有其他全局符号则隐藏,以便通过 -fvisibility=hidden ? 下面是一个简单介绍:

    让我们从以下几点开始:

    矩形.cpp(1)

    class Rectangle {
        int width, height;
      public:
        void set_values (int,int);
        int area() {return width*height;}
    
    };
    
    void Rectangle::set_values (int x, int y) {
      width = x;
      height = y;
    }
    

    rectangle.o

    $ g++ -Wall -c -fPIC rectangle.cpp
    

    然后检查全局符号表:

    $ nm -C rectangle.o
    0000000000000000 T Rectangle::set_values(int, int)
    

    请注意 Rectangle::area 是不是有。不适用于 完全 因此,它的动态可见性问题就不会出现。

    那是因为它是被定义的 内联 在类定义中,从未调用 在编译单元中,所以gcc甚至不需要编译它的定义。它消失了

    Rectangle::set_values 另一方面,没有内联定义,因此编译器 发射全局符号和定义。

    使 符合某种可见性类型,我们首先需要 它通过不内联定义来定义全局符号:

    矩形.cpp(2)

    class Rectangle {
        int width, height;
      public:
        void set_values (int,int);
        int area();
    
    };
    
    int Rectangle::area() {return width*height;}
    
    void Rectangle::set_values (int x, int y) {
      width = x;
      height = y;
    }
    

    重新编译并再次检查全局符号表:

    $ g++ -Wall -c -fPIC rectangle.cpp
    $ nm -C rectangle.o
    000000000000001a T Rectangle::set_values(int, int)
    0000000000000000 T Rectangle::area()
    

    矩形::面积 出现。

    接下来,让我们创建一个共享库 librectangle.so 矩形.o

    $ g++ -o librectangle.so --shared rectangle.o
    

    这是你的名字 Rectangle::*

    $ nm -C librectangle.so | grep 'Rectangle::'
    00000000000005d4 T Rectangle::set_values(int, int)
    00000000000005ba T Rectangle::area()
    

    下面是 矩形:* 动态 符号表:

    $ nm -CD librectangle.so | grep 'Rectangle::'
    00000000000005d4 T Rectangle::set_values(int, int)
    00000000000005ba T Rectangle::area()
    

    他们是一样的。

    现在让我们隐藏这些动态链接符号。我们需要 重新编译 rectangle.cpp 然后重新链接共享库:

    $ g++ -Wall -c -fPIC -fvisibility=hidden rectangle.cpp
    $ g++ -o librectangle.so --shared rectangle.o
    

    矩形:* 现在在全局符号表中的符号:

    $ nm -C librectangle.so | grep 'Rectangle::'
    0000000000000574 t Rectangle::set_values(int, int)
    000000000000055a t Rectangle::area()
    

    下面是 矩形:* 符号现在在 动态

    $ nm -CD librectangle.so | grep 'Rectangle::'; echo Done
    Done
    

    没有人 ,感谢 -可视性=隐藏 .

    最后,让我们做一个 矩形::面积 动态可见,保持所有 再一次:

    矩形.cpp(3)

    class Rectangle {
        int width, height;
      public:
        void set_values (int,int);
        __attribute__((visibility("default"))) int area();
    
    };
    
    int Rectangle::area() {return width*height;}
    
    void Rectangle::set_values (int x, int y) {
      width = x;
      height = y;
    }
    

    然后重新编译并重新链接:

    $g++-o librectangle.so—共享矩形.o
    

    全局符号表仍显示:

    $ nm -C librectangle.so | grep 'Rectangle::'
    00000000000005a4 t Rectangle::set_values(int, int)
    000000000000058a T Rectangle::area()
    

    $ nm -CD librectangle.so | grep 'Rectangle::'
    000000000000058a T Rectangle::area()
    

    矩形::面积 现在是共享库为其公开的唯一符号

    还有一件事:

    是否可以将area()设置为public,并将\u值(int,int)设置为local,如第一个链接所示,而不更改代码?

    为动态链接隐藏符号并不意味着 地方的 是的属性 全球的 地方的 符号不存在。唯一的办法 使符号成为本地的,否则将是全局的are:-

    则符号不会出现在全局或动态符号表中。