是否可以通过修改上面的编译命令来定制公开哪些函数?
不,编译选项-fvisibility=[default|internal|hidden|protected]
是否可以在不改变代码的情况下,如第一个链接所示,将area()设置为公共并将_值(int,int)设置为本地?
也没有.
如何将源代码更改为Rectangle::area()
动态
让我们从以下几点开始:
rectangle.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;
}
只需将其编译成PIC rectangle.o
即可:
$ g++ -Wall -c -fPIC rectangle.cpp
然后判断全局符号表:
$ nm -C rectangle.o
0000000000000000 T Rectangle::set_values(int, int)
请注意,Rectangle::area
并不存在.这对我来说是不可用的
这是因为它在类定义中被定义为inline,并且从未被调用
另一方面,Rectangle::set_values
不是内联定义的,因此编译器
要使Rectangle::area
符合某种可见性类型,我们首先需要
rectangle.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()
好的现在,Rectangle::area
的全球定义出现了.
接下来,让我们从rectangle.o
创建一个共享库librectangle.so
:
$ 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()
下面是dynamic符号表中的Rectangle::*
个符号:
$ nm -CD librectangle.so | grep 'Rectangle::'
00000000000005d4 T Rectangle::set_values(int, int)
00000000000005ba T Rectangle::area()
他们是一样的.
现在,让我们隐藏这些符号以进行动态链接.我们需要recompile rectangle.cpp
$ g++ -Wall -c -fPIC -fvisibility=hidden rectangle.cpp
$ g++ -o librectangle.so --shared rectangle.o
下面是全局符号表中的Rectangle::*
个符号:
$ nm -C librectangle.so | grep 'Rectangle::'
0000000000000574 t Rectangle::set_values(int, int)
000000000000055a t Rectangle::area()
他们和以前一样.
下面是dynamic符号表中的Rectangle::*
个符号:
$ nm -CD librectangle.so | grep 'Rectangle::'; echo Done
Done
现在有none个,多亏了-fvisibility=hidden
个.
最后,让我们只动态显示Rectangle::area
个,保持所有
rectangle.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++ -Wall -c -fPIC -fvisibility=hidden rectangle.cpp
$ g++ -o librectangle.so --shared rectangle.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()
Rectangle::area
现在是共享库公开的唯一符号
And before you go...
还有一件事:
是否可以在不改变代码的情况下,如第一个链接所示,将area()设置为公共并将_值(int,int)设置为本地?
为动态链接隐藏符号并不等于local.动态可见性(默认|内部|隐藏|保护)
则符号不会出现在全局或动态符号表中.