linux 清理共享函数,Linux 共享库中函数的可见性

Linux共享库中的函数,默认都是可以外部可见的,也就是不需要像Windows下通过DEF文件或者dllexport指令来导出。先写一个源文件:MyExportFunctions.cpp,内容如下:

1

2

3

4

5

6

int Add(int a, int b){

return a + b;

}

int Sub(int a, int b){

return a - b;

}

用gcc编译成共享库:

1

gcc -shared -o libExportFunctions.so MyExportFunctions.cpp

用nm -g命令看查看所有导出的函数,Add和Sub都已经导出了。

1

2

3

4

5

6

7

8

9

10

11

12

13

nm -g libExportFunctions.so

0000000000201028 B __bss_start

w __cxa_finalize@@GLIBC_2.2.5

0000000000201028 D _edata

0000000000201030 B _end

00000000000006ac T _fini

w __gmon_start__

0000000000000550 T _init

w _ITM_deregisterTMCloneTable

w _ITM_registerTMCloneTable

w _Jv_RegisterClasses

0000000000000680 T _Z3Addii

0000000000000694 T _Z3Subii

不过为什么函数名不是Add和Sub,而是_Z3Addii和_Z3Subii (可以给nm 加上参数 –demangle来把c++修饰后的名字翻译回来,也可以用c++filt这个命令来转换),这是因为这两个函数是在c++源文件里声明的,而c++编译器会给函数名自动加上一些修饰符,解决方法就是加extern “C”.

1

2

3

4

5

6

7

8

extern "C"{

int Add(int a, int b){

return a + b;

}

int Sub(int a, int b){

return a - b;

}

}

nm -g 的结果是这样

1

2

3

4

5

6

7

8

9

10

11

12

13

nm -g libExportFunctions.so

0000000000000670 T Add

0000000000201028 B __bss_start

w __cxa_finalize@@GLIBC_2.2.5

0000000000201028 D _edata

0000000000201030 B _end

000000000000069c T _fini

w __gmon_start__

0000000000000540 T _init

w _ITM_deregisterTMCloneTable

w _ITM_registerTMCloneTable

w _Jv_RegisterClasses

0000000000000684 T Sub

这样Add和Sub都是原来的名字了。

那怎么样只导出需要的函数呢?gcc的一篇关于可见性的wiki说得挺详细gcc函数可见性

先在编译时用-fvisibility=hidden把函数都改成默认不可见 ,然后在需要导出函数的声明前加attribute ((visibility (“default”)))。修改后的代码

1

2

3

4

5

6

7

8

extern "C"{

__attribute__ ((visibility ("default"))) int Add(int a, int b){

return a + b;

}

int Sub(int a, int b){

return a - b;

}

}

然后在编译时加上-fvisibility=hidden

1

gcc -shared -fvisibility=hidden -o libExportFunctions.so MyExportFunctions.cpp

这次nm -g的输出中就只有Add,没有Sub了

1

2

3

4

5

6

7

8

9

10

11

12

nm -g libExportFunctions.so

0000000000000660 T Add

0000000000201028 B __bss_start

w __cxa_finalize@@GLIBC_2.2.5

0000000000201028 D _edata

0000000000201030 B _end

000000000000068c T _fini

w __gmon_start__

0000000000000528 T _init

w _ITM_deregisterTMCloneTable

w _ITM_registerTMCloneTable

w _Jv_RegisterClasses

上面说的这种方式类似Windows下的dllexport指令,那有没有跟DEF文件类似的东西可以在配置文件里配置哪些函数是导出的呢?gcc也有类似的配置文件,可以看GNU Export Maps。用法很简单,创建一个文本文件,叫exportmap,内容是这样

1

2

3

4

{

global: Sub;

local: *;

};

然后编译时带–version-script参数

1

gcc -shared -Wl,--version-script=exportmap -o libExportFunctions.so MyExportFunctions.cpp

用nm -g查看,结果是

1

2

3

4

5

6

7

nm -g libExportFunctions.so

w __cxa_finalize@@GLIBC_2.2.5

w __gmon_start__

w _ITM_deregisterTMCloneTable

w _ITM_registerTMCloneTable

w _Jv_RegisterClasses

00000000000005b4 T Sub

0b1331709591d260c1c78e86d0c51c18.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值