linux下动态库的使用

    xiaoxiao2021-03-25  106

    动态库的调用分为隐式调用和显式调用

    动态库的编写

    动态库是由源文件编译而成的,与普通程序不同的是,动态库没有main函数,不能单独执行,需要被调用才能执行。

    写一个四则运算的动态库

    calculate.h文件

    #ifndef CALCULATE_H_H #define CALCULATE_H_H //加法 int add(int a, int b); //减法 int sub(int a, int b); //乘法 int mul(int a, int b); //除法 int div(int a, int b); #endif calculate.c文件 #include "calculate.h" //加法 int add(int a, int b) { return a+b; } //减法 int sub(int a, int b) { return a-b; } //乘法 int mul(int a, int b) { return a*b; } //除法 int div(int a, int b) { return a/b; } 将源文件编译成动态库

    gcc -shared -fpic calculate.c -o libcal.so

    linux下的动态库的后缀名都是.so

    隐式调用

    动态库写好了,下面开始调用,先看看隐式调用。

    main.c

    #include <stdio.h> #include "calculate.h" int main() { int a = 6 , b = 2; printf("%d + %d = %d\n", a, b, add(a, b)); printf("%d - %d = %d\n", a, b, sub(a, b)); printf("%d * %d = %d\n", a, b, mul(a, b)); printf("%d / %d = %d\n", a, b, div(a, b)); return 0; } 可以看出,隐式调用只需要包含动态库的头文件就行了。接下来编译main.c程序。

    gcc main.c -o main -L . -lcal

    gcc main.c -o main -L . libcal.so

    上述两种编译方法都可以。-L后跟的是我们动态库所在的目录,我们将动态库和main.c程序放一起了,所以目录就是当前目录。后面-lcal是去除动态库名字的lib和后缀。或者直接写动态库名字也可以。

    下面执行程序

    我们发现了错误,找不到该动态库。问题就在于虽然指定了动态库的路径,但运行时还是会从系统默认的动态库路径中去查找。所以解决办法就是讲我们写的动态库路径加入到系统的动态库路径中去。如果程序中使用了很多动态库,那就需要先看看是哪个动态库不能找到,方法就是

    ldd main

    可以看到的确是libcal.so这个动态库未找到。

    下面开始添加。

    /etc/ld.so.conf.d/目录下新建动态库相应的配置文件calculate.conf 添加上动态库的绝对路径: /home/zxin/dynamic_libiary

    使配置生效

    sudo ldconfig

    接着我们重新运行main程序

    成功!

    显示调用

    显示调用如下。需要加载动态库--定位所需要的函数--调用该函数。需要用到头文件<dlfcn.h>以及dlopen、dlsym、 dlclose等函数。

    new_main.c

    #include <stdio.h> #include <dlfcn.h> #define DLL_FILE_NAME "libcal.so" int main() { void *handle; typedef int(*pFun)(int , int); handle = dlopen(DLL_FILE_NAME, RTLD_NOW); //加载动态库 if (handle == NULL) { printf("Failed to open dll file : %s. error: %s\n", DLL_FILE_NAME, dlerror()); exit(1); } int a = 6, b = 2; pFun func; func = dlsym(handle, "add");//定位动态库中的函数 printf("%d + %d = %d\n", a, b, func(a, b));//调用动态库中的函数 func = dlsym(handle, "sub"); printf("%d - %d = %d\n", a, b, func(a, b)); func = dlsym(handle, "mul"); printf("%d * %d = %d\n", a, b, func(a, b)); func = dlsym(handle, "div"); printf("%d / %d = %d\n", a, b, func(a, b)); dlclose(handle);//动态库的引用计数减一 return 0; } 编译

    gcc new_main.c -o new_main -ldl 注意要加上-ldl选项,以使用显示调用相关的函数。

    结果:

    虽然显示调用比隐式调用步骤要稍复杂点,但显示调用更灵活。

    动态库与静态库比较

    动态库是在主程序运行时才会调用库里面的函数,动态库不用和程序一起编译,所以更新起来方便,原来编译好的程序不用重新编译就可使用更新后的动态库。而静态库就需要和程序一起编译,更新起来就麻烦,库更新则使用库的程序也需要更新。另,静态库是被编译到程序中的,所以编译后程序较大。相比较而言使用动态库的程序就比较小。

    总结:1.使用动态库的程序无需更新,只需要更新动态库。而使用静态库的程序还需重新编译。2.使用动态库的程序更小。

    参考文章:http://blog.csdn.net/leichelle/article/details/7465763

    转载请注明原文地址: https://ju.6miu.com/read-5492.html

    最新回复(0)