实用指南:嵌入式开发学习(第二阶段 C语言笔记)
库文件
什么是库文件
库文件本质上是经过编译后生成的可被计算机执行的二进制代码。但注意库文件不能独立运行,库文件需要加载到内存中才能执行。库文件大量存在于Windows,Linux,MacOS等软件平台上。
库文件的分类
- 静态库
- Windows:xxx.lib
- Linux:libxxx.a
- 动态库(共享库)
- Windows:xxx.dlll
- Linux:libxxxx.so.major.minor(libmy.so.1.1)
注意:不同的软件平台因编译、链接器的不同,所生成的库文件是不兼容的。
静态库与动态库的区别
- 静态库链接时,将库中所有内容包含到最终的可执行程序中。
动态库链接时,将库中的符号信息包含到最终可执行文件中,在程序运行时,才将动态库中符号的具体实现加载到内存中。
静态库与动态库的优缺点
- 静态库
- 优点:生成的可执行程序不再依赖静态文件
- 缺点:可执行程序体积较大
- 动态库
- 优点:生成的可执行程序体积小;动态库可被多个应用程序共享
- 缺点:可执行程序运行依然依赖动态库文件
静态库与动态库对比

库文件创建
Linux系统下库文件命名规范:libxxxx.a(静态库) libxxxx.so(动态库)
静态库文件的生成
- 将需要生成库文件对应的源文件( *.c )通过编译(不链接)生成 *.o 目标文件
- 用
ar命令将生成的*.o打包生成libxxxx.a
库的生成:
库的使用 :

动态库文件的生成
- 利用源文件(
*.c)通过编译(不链接)生成位置无关*.o目标文件 - 将目标文件链接为
*.so文件
库的生成:

库的使用:

注意:如果在代码编译过程或者运行中链接了库文件,系统会到 /lib 和 /usr/lib 目录下查找库文件,所以建议直接将库文件放在 /lib 或者/usr/lib,否则系统可能无法找到库文件,造成编译或者运行错误 。
扩展内容
查看应用程序(例如:app)依赖的动态库

动态库使用方式:
编译时链接动态库,运行时系统自动加载动态库
程序运行时,手动加载动态库
实现:
涉及内容
- 头文件:#include <dlfcn.h>
- 接口函数:dlopen、dlclose、dlsym
- 依赖库:-ldl
- 句柄handler:资源的标识
示例代码
# include <stdio.h> # include <dlfcn.h> int main( int argc, char *argv[] ) { // 1. 加载动态库 "/lib/libdlfun.so" // - RTLD_LAZY: 延迟绑定(使用时才解析符号,提高加载速度) // - 返回 handler 是动态库的句柄,失败时返回 NULL void* handler = dlopen("/lib/libdlfun.so" , RTLD_LAZY) ; if (handler == NULL ) { // 打印错误信息(dlerror() 返回最后一次 dl 相关错误的字符串) fprintf(stderr , "dlopen 失败: %s\n" , dlerror( ) ) ; return -1 ; } // 2. 从动态库中查找符号 "sum"(函数名) // - dlsym 返回 void*,需强制转换为函数指针类型 int sum(int*arr, int size); // - 这里假设 "sum" 是一个接受两个int*,int参数、返回 int 的函数 int (*paddr)( int* , int ) = ( int (* )( int* , int ) )dlsym(handler,"sum" ) ; if (paddr == NULL ) { fprintf(stderr , "dlsym 失败: %s\n" , dlerror( ) ) ; dlclose(handler) ; // 关闭动态库(释放资源) return -1 ; } // 3. 调用动态库中的函数 "sum",计算{11,12,13,14,15}的累加和 int arr[5] = { 11 ,12 ,13 ,14 ,15 } ; printf("sum=%d\n" , paddr(arr, sizeof(arr)/ sizeof(arr[0] ) ) ) ; // 4. 关闭动态库(释放内存和资源) dlclose(handler) ; return 0 ; }编译命令
gcc demo06.c -ldl
浙公网安备 33010602011771号