C语言 --- 动态库的两种使用方式说明
概述 动态库的使用分为两种方式(按照编码内容,编译方式及动态库加载时机来区分):
-
显示调用 隐式调用
1、动态库的制作
动态库测试内容如下:
-
动态库对应的源文件 “test_lib.c”
#include "stdio.h" void test_print(void) { printf("======= This is a test line. "); return; }
-
动态库对应的头文件 “test_lib.h”
void test_print(void);
编译命令如下:
gcc test_lib.c -fPIC -shared -o libtest.so 说明: -fPIC :表示生成位置无关代码(PIC:Position Independent Code) -shared : 表示创建生成动态共享库
2、隐式调用(程序启动运行前加载动态库) 在代码中没有指明需要的动态库,只包含库的头文件和库函数,需要在编译时来指明需要的动态库,软件启动运行前会加载动态库。
测试文件 test_bin1.c 内容如下:
#include <stdio.h> #include "test_lib.h" int main(void) { printf("========= start... "); test_print(); return 0; }
编译命令如下(和链接静态库命令基本一样):
gcc test_bin1.c -L. -ltest -o test1 说明:编译的时候指定了libtest.so(上述编译好的动态库)
测试1:没有指定动态库路径,且没有将生成的动态库拷贝到系统路径下,测试结果如下图: Error:报错找不到动态库 libtest.so
没有打印main函数入口的内容,说明动态库加载是在软件启动时进行的。
测试2:指定动态库的路径后(也可以将动态库复制到系统目录下),测试结果如下图:
3、显示调用 (程序运行过程中加载动态库) 在代码中明确指出需要的动态库,不用在编译时指定。软件运行过程中,使用特定的函数来加载动态库,使用特定函数通过符号名来查找动态库内的函数或变量,并调用。
测试文件 test_bin2.c 内容如下:
#include <stdio.h> #include <dlfcn.h> #include "test_lib.h" int main(void) { void * handle = NULL; void (* pFuc)(void) = NULL; //函数指针 printf("========= start... "); handle = dlopen("libtest.so", RTLD_NOW); //打开动态库 if (handle == NULL) { printf("%s ", dlerror()); return -1; } pFuc = dlsym(handle, "test_print"); // 查找需要使用的符号 if ((pFuc != NULL) && (NULL == dlerror()) ) { pFuc(); // 调用动态库中的函数 } else { printf("get test_print FUNC failed. "); } dlclose(handle); // 卸载动态库 return 0; }
编译命令如下:
gcc test_bin2.c -ldl -o test2 说明:不需要指定libtest.so,但是需要链接libdl.so(或者libdl.a)库,因为使用了libdl库中的函数
测试1:没有指定动态库路径,测试结果如下图: Error::报错找不到动态库 libtest.so
有打印main函数入口的内容,说明软件是可以启动的,动态库是在软件运行过程中加载的。
测试2:指定动态库的路径后,测试结果如下图: 4、附录 对应测试例子的Makefile文件如下:
all: test1 test2 test1:test_bin1.c libtest.so gcc test_bin1.c -L. -ltest -o test1 test2:test_bin2.c gcc test_bin2.c -ldl -o test2 libtest.so:test_lib.c gcc $^ -fPIC -shared -o $@ clean: rm -f libtest.so test1 test2 .PHONY: clean all
下一篇:
模拟翻译软件(java)