Linux之动态链接库

  • Post author:
  • Post category:linux















Linux





下创建与使用动态库













linux





动态库的命名规则







动态链接库的名字形式为






libxxx.so




,前缀是




lib




,后缀名为“




.so






”。








l














针对于实际库文件,每个共享库都有个特殊的名字“






soname






”。在程序启动后,程序通过这个名字来告诉动态加载器该载入哪个共享库。








l














在文件系统中,






soname




仅是一个链接到实际动态库的链接。对于动态库而言,每个库实际上都有另一个名字给编译器来用。它是一个指向实际库镜像文件的链接文件(




lib+soname+.so






)。






创建动态库(





.so












编写四则运算动态库代码:







DynamicMath.h






头文件








#pragma once







class DynamicMath







{








public:



















DynamicMath(void);




















~DynamicMath(void);




























static double add(double a, double b);//¼Ó·¨




















static double sub(double a, double b);//¼õ·¨




















static double mul(double a, double b);//³Ë·¨




















static double div(double a, double b);//³ý·¨




















void print();








};














l













首先,生成目标文件,此时要加编译器选项

-fpic







g++ -fPIC -c DynamicMath.cpp







-fPIC






创建与地址无关的编译程序(




pic









position independent code






),是为了能够在多个应用程序间共享。








l













然后,生成动态库




,此时要加链接器选项



-shared







g++ -shared -o libdynmath.so DynamicMath.o







-shared






指定生成动态链接库。





clip_image025[4]




其实上面两个步骤可以合并为一个命令:





g++

-fPIC -shared

-o libdynmath.so DynamicMath.cpp










使用动态库





编写使用动态库的测试代码:






测试代码:







#include “../DynamicLibrary/DynamicMath.h”















#include







using namespace std;















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







{
















double a = 10;
















double b = 2;
























cout << “a + b = ” << DynamicMath::add(a, b) << endl;
















cout << “a – b = ” << DynamicMath::sub(a, b) << endl;
















cout << “a * b = ” << DynamicMath::mul(a, b) << endl;
















cout << “a / b = ” << DynamicMath::div(a, b) << endl;
























DynamicMath dyn;

















dyn.print();
















return 0;








}






引用动态库编译成可执行文件(跟静态库方式一样):





g++ TestDynamicLibrary.cpp -L../DynamicLibrary -ldynmath






然后运行:






./a.out






,发现竟然报错了!!!





clip_image027[4]




可能大家会猜测,是因为动态库跟测试程序不是一个目录,那我们验证下是否如此:




clip_image029[4]




发现还是报错!!!那么,在执行的时候是如何定位共享库文件的呢?







1)




















当系统加载可执行代码时候,能够知道其所依赖的库的名字,但是还需要知道绝对路径。此时就需要系统动态载入器






(dynamic linker/loader)















2)




















对于






elf




格式的可执行程序,是由




ld-linux.so*




来完成的,它先后搜索




elf




文件的




DT_RPATH




段—环境变量




LD_LIBRARY_PATH









/etc/ld.so.cache




文件列表—




/lib/,/usr/lib






目录找到库文件后将其载入内存。






如何让系统能够找到它:







l














如果安装在






/lib




或者




/usr/lib




下,那么




ld






默认能够找到,无需其他操作。








l














如果安装在其他目录,需要将其添加到






/etc/ld.so.cache






文件中,步骤如下:








n














编辑






/etc/ld.so.conf






文件,加入库文件所在目录的路径








n














运行






ldconfig




,该命令会重建




/etc/ld.so.cache






文件







我们将创建的动态库复制到






/usr/lib






下面,然后运行测试程序。





clip_image031[4]










Linux





下显式调用动态库







#include






,提供了下面几个接口:








l














void *

dlopen

( const char * pathname, int mode )






:函数以指定模式打开指定的动态连接库文件,并返回一个句柄给调用进程。








l














void*

dlsym

(void* handle,const char* symbol)











dlsym




根据动态链接库操作句柄




(pHandle)




与符号




(symbol)






,返回符号对应的地址。使用这个函数不但可以获取函数地址,也可以获取变量地址。








l














int

dlclose

(void *handle)











dlclose




用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为




0









,






才会真正被系统卸载。








l














const char *dlerror(void)






:当动态链接库操作函数执行失败时,




dlerror




可以返回出错信息,返回值为




NULL






时表示操作函数执行成功。






本文转自:




http://www.cnblogs.com/skynet/p/3372855.html