linux下ld连接SO文件时如何制定绝对路径

linux下ld连接SO文件时如何制定绝对路径,第1张

连接器使用下面的搜索路径来定位需要的共享库: 1. 所有由"-rpath-link"选项指定的搜索路径. 2. 所有由"-rpath"指定的搜索路径. “-rpath"跟"-rpath_link"的不同之处在于,由"-rpath"指定的路径被包含在可执行文件中,并在运行时使用, 而"-rpath-link"选项仅仅在连接时起作用. 它只用于本地连接器. 3. 在一个ELF系统中, 如果"-rpath"和"rpath-link"选项没有被使用, 会搜索环境变量"LD_RUN_PATH"的内容.它也只对本地连接器起作用. 4. 在SunOS上, “-rpath"选项不使用, 只搜索所有由"-L"指定的目录. 5. 对于一个本地连接器,环境变量"LD_LIBRARY_PATH"的内容被搜索. 6. 对于一个本地ELF连接器,共享库中的`DT_RUNPATH"和`DT_RPATH" *** 作符会被需要它的共享库搜索. 如果"DT_RUNPATH"存在了, 那"DT_RPATH"就会被忽略. 7. 缺省目录, 常规的,如"/lib"和"/usr/lib". 8. 对于ELF系统上的本地连接器, 如果文件"/etc/ld.so.conf"存在, 这个文件中有的目录会被搜索.

如上所述,可以用"-rpath-link","-rpath",或者文件"/etc/ld.so.conf"来指定。

为了升级方便,举个例子来说,有个共享库的文件名字叫作libfoo.so.1,某客户程序使用该库的功能,编写代码后编译成功了。在连接生成二进制文件的客户程序时,正规的做法是建立一个libfoo.so.1文件的符号链接,名字通常会叫做libfoo.so,于是客户程序的连接参数应该写成-lfoo,连接生成二进制文件后我们使用ldd命令可以看到客户程序依赖于libfoo.so.1这个库文件。

此后,libfoo.so的开发者决定升级该库,但是发布文件的时候文件名改成了libfoo.so.2,并且重新生成符号链接文件libfoo.so指向libfoo.so.2这个新版的共享库。这样做的好处是客户程序在重新编译的时候无需更改Makefile文件,仍然使用-lfoo这个连接参数即可。

实例代码(soTest.c):

1 #include <stdio.h>

2 #include <dlfcn.h>

3

4 int main(int argc, char *argv[]){

5 void * libm_handle = NULL

6 float (*cosf_method)(float)

7 char *errorInfo

8 float result

9

10 // dlopen 函数还会自动解析共享库中的依赖项。这样,如果您打开了一个依赖于其他共享库的对象,它就会自动加载它们。

11 // 函数返回一个句柄,该句柄用于后续的 API 调用

12 libm_handle = dlopen("libm.so", RTLD_LAZY )

13 // 如果返回 NULL 句柄,表示无法找到对象文件,过程结束。否则的话,将会得到对象的一个句柄,可以进一步询问对象

14 if (!libm_handle){

15 // 如果返回 NULL 句柄,通过dlerror方法可以取得无法访问对象的原因

16 printf("Open Error:%s.\n",dlerror())

17 return 0

18 }

19

20 // 使用 dlsym 函数,尝试解析新打开的对象文件中的符号。您将会得到一个有效的指向该符号的指针,或者是得到一个 NULL 并返回一个错误

21 cosf_method = dlsym(libm_handle,"cosf")

22 errorInfo = dlerror()// 调用dlerror方法,返回错误信息的同时,内存中的错误信息被清空

23 if (errorInfo != NULL){

24 printf("Dlsym Error:%s.\n",errorInfo)

25 return 0

26 }

27

28 // 执行“cosf”方法

29 result = (*cosf_method)(0.0)

30 printf("result = %f.\n",result)

31

32 // 调用 ELF 对象中的目标函数后,通过调用 dlclose 来关闭对它的访问

33 dlclose(libm_handle)

34

35 return 0

36 }

在这个例子中主要是调用了 math 库(libm.so)中的“cosf”函数,dlopen函数的第二个参数表示加载库文件的模式,主要有两种:RTLD_LAZY 暂缓决定,等有需要时再解出符号;RTLD_NOW 立即决定,返回前解除所有未决定的符号。另外记得引用包含API的头文件“#include <dlfcn.h>”(^_^)。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/8350442.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-15
下一篇 2023-04-15

发表评论

登录后才能评论

评论列表(0条)

保存