我有一个这样的示例程序:
#include <stdio.h>
#if 1
#define FOR_EXPORT __attribute__ ((visibility("hidden")))
#else
#define FOR_EXPORT
#endif
FOR_EXPORT void mylocalfunction1(void)
{
printf("function1\n");
}
void mylocalfunction2(void)
{
printf("function2\n");
}
void mylocalfunction3(void)
{
printf("function3\n");
}
void printMessage(void)
{
printf("Running the function exported from the shared library\n");
}
Run Code Online (Sandbox Code Playgroud)
并使用编译它
gcc -shared -fPIC -fvisibility=hidden -o libdefaultvisibility.so defaultvisibility.c
Run Code Online (Sandbox Code Playgroud)
现在编译完成后我做了:
$ nm libdefaultvisibility.so
nm libdefaultvisibility.so
0000000000000eb0 t _mylocalfunction1
0000000000000ed0 t _mylocalfunction2
0000000000000ef0 t _mylocalfunction3
0000000000000f10 t _printMessage
U _printf
U dyld_stub_binder
Run Code Online (Sandbox Code Playgroud)
这意味着尽管-fvisibility=hidden所有符号都被导出,但据我所知.我所遵循的这本书声称只有标记的功能FOR_EXPORT才能导出.
我看了几个其他资源,但对于我正在做的简单测试-fvisibility=hidden应该足够了.
我的铿锵版:
$ clang -v
clang -v
Apple LLVM version 7.3.0 (clang-703.0.31)
Target: x86_64-apple-darwin15.0.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
Run Code Online (Sandbox Code Playgroud)
你误解了输出nm.滚动浏览man nm,您会看到该t标志表示该符号是该text部分中的本地(静态)符号.链接器无法看到它.如果它是全局的(外部的)旗帜将是T.所以你的所有四个功能都是本地的.
对比:
$ clang -shared -fPIC -fvisibility=hidden -o libdefaultvisibility.so defaultvisibility.c
$ nm libdefaultvisibility.so | grep ' t '
0000000000000570 t deregister_tm_clones
0000000000000600 t __do_global_dtors_aux
0000000000200e08 t __do_global_dtors_aux_fini_array_entry
0000000000000640 t frame_dummy
0000000000200e00 t __frame_dummy_init_array_entry
0000000000000670 t mylocalfunction1
0000000000000690 t mylocalfunction2
00000000000006b0 t mylocalfunction3
00000000000006d0 t printMessage
00000000000005b0 t register_tm_clones
Run Code Online (Sandbox Code Playgroud)
放弃了-fvisibility=hidden:
$ clang -shared -fPIC -o libdefaultvisibility.so defaultvisibility.c
$ nm libdefaultvisibility.so | grep ' t '
0000000000000600 t deregister_tm_clones
0000000000000690 t __do_global_dtors_aux
0000000000200e08 t __do_global_dtors_aux_fini_array_entry
00000000000006d0 t frame_dummy
0000000000200e00 t __frame_dummy_init_array_entry
0000000000000700 t mylocalfunction1
0000000000000640 t register_tm_clones
$ nm libdefaultvisibility.so | grep ' T '
0000000000000780 T _fini
00000000000005b0 T _init
0000000000000720 T mylocalfunction2
0000000000000740 T mylocalfunction3
0000000000000760 T printMessage
Run Code Online (Sandbox Code Playgroud)
然后只有明确隐藏的mylocalfunction1仍然是本地的,其他三个现在是全局的.
__attribute__ ((visibility("hidden")))
在任何情况下,您都不应期望标记的符号将由共享库导出.该属性精确地表示它不会是,它是否显式应用于符号,如本例所示,或者在链接器选项存在时默认获取-fvisibility=hidden.
如果您想通过visibility属性导出示例中的那一个函数,您将拥有:
#define FOR_EXPORT __attribute__ ((visibility("default")))
Run Code Online (Sandbox Code Playgroud)
然后:
$ clang -shared -fPIC -fvisibility=hidden -o libdefaultvisibility.so defaultvisibility.c
$ nm libdefaultvisibility.so | grep ' T '
0000000000000720 T _fini
0000000000000550 T _init
00000000000006a0 T mylocalfunction1
Run Code Online (Sandbox Code Playgroud)
它是全局的,因为显式归因会覆盖命令行选项,而您的所有其他功能都是本地的.也许令人困惑,default可见性总是公开的.
你可以不诉诸做到这一点visibility不属于便携式- -简单地宣布所有你的职能归属不希望导出的static.然后编译器首先不会将它们暴露给链接器:
foo.c的
#include <stdio.h>
void mylocalfunction1(void)
{
printf("function1\n");
}
static void mylocalfunction2(void)
{
printf("function2\n");
}
static void mylocalfunction3(void)
{
printf("function3\n");
}
static void printMessage(void)
{
printf("Running the function exported from the shared library\n");
}
Run Code Online (Sandbox Code Playgroud)
你再次获得: -
$ clang -shared -fPIC -o libfoo.so foo.c
$ nm libfoo.so | grep ' T '
00000000000006c0 T _fini
0000000000000550 T _init
00000000000006a0 T mylocalfunction1
Run Code Online (Sandbox Code Playgroud)
虽然在您的示例中没有感觉到这种区别,但您应该理解,虽然链接器看不到本地/静态符号,并且(因此)不可用于动态链接,但是全局/外部符号
可能可用或不可用于动态连锁.visibility
仅控制动态链接的全局符号的可用性.