我最开始开发时,所有代码在一块儿;

后来我想把一部分基础的函数分离出来,做成so;

但因为没有一开始就分离,结果:想分离的函数用了不少全局变量;编译so没问题,主程序加载so就出问题了,报变量符号找不到。

各种搜索无果,最后发现:

在linux上,链接主程序的时候,使用参数-Wl,--export-dynamic

在AIX上,使用'deferred imports' 并且 enable 'runtime linking'.

在主程序编译时加上:-Wl,--export-dynamic;问题就解决了。

加载so代码:

if((handle = dlopen(file_name, RTLD_NOW)) == NULL) {
		printf("[LibAes] dlopen error - %s\n", dlerror());
		return NULL;
	}

原理:

“--export-dynamic”参数的使用

GCC编译可执行文件时可以使用-Wl,--export-dynamic参数,此时链接器产生可执行文件时会将所有全局符号导出到动态符号表。

gcc -Wl,--export-dynamic -o p1 p1.c -L. -l0

如果在创建动态链接的可执行文件不加-Wl,--export-dynamic选项,则它所export的动态符号仅仅包括在链接时动态对象所用到的。因为dlopen是自行加载动态库,并不存在与可执行文件动态符号解析的过程,所以如果dlopen加载的动态库使用了主模块中定义的函数,则会出现找不到符号的情况。

默认链接器在产生可执行文件时,只会将那些链接时被其他共享模块引用到的符号放到动态符号表中,这样可以减少动态符号表的大小,也就是说,在共享模块中反向引用主模块中的符号时,只有那些在链接时被共享模块引用到的符号才会被导出。(主模块的符号表中依赖的共享模块主模块才会去链接,否则不会去链接,不被链接的模块引用了主模块的符号就不会被导出到动态符号表中,导致运行时报错)。

但是使用--export-dynamic参数后由于将所有的全局符号导出到动态符号表中导致可执行程序会变大。

================

反过来,主程序想使用动态库的全局变量,我稍微试了下,没成功!

不管了,现在我已经很满意了!

Logo

更多推荐