记录下Linux下编译和链接动态库的过程。
2016-07-29 13:30
369 查看
一、 编写动态库
头文件so.h:
实现文件so.c:
解释一下各个参数含义:
-fPIC:生成位置无关代码(Position Independent Code),只有生成PIC才能通过虚拟页映射达到可执行代码在进程间共享,从而节省内存的目的。
说明我们要生成的是动态库so(Shared Object)文件,从而进行动态链接。
通过
编写主程序main.c:
使用
-L:添加库文件的搜索路径
-l:指定需要链接的库。该名称是处在头lib和后缀.so中的名称,如上动态库libtest.so的l参数为-l test
此时通过
section里依赖libtest.so了
dynamic symbols中也有一个undefined symbol(add)
在执行隐式链接的程序之前要注意设置
编写主程序dyn_main.c
使用
这时通过
dyn_test的dynamic symbols中也没有add:
运行程序也不需要设置
原文出处忘了,看到烦请说一声
参考资料:
Linux动态库的编译与使用 转载
详细分析Linux动态库的使用方式
How do I list the symbols in a .so file
Import names in ELF binary
头文件so.h:
#ifndef SO_H#define SO_H int add(int a, int b); #endif /*SO_H*/
实现文件so.c:
#include "so.h" int add(int a, int b){ return a + b;}
二、编译动态库
gcc so.c -fPIC -shared -o libtest.so
解释一下各个参数含义:
-fPIC:生成位置无关代码(Position Independent Code),只有生成PIC才能通过虚拟页映射达到可执行代码在进程间共享,从而节省内存的目的。
说明我们要生成的是动态库so(Shared Object)文件,从而进行动态链接。
通过
nm -g libtest.so可以看到,导出符号表中已经有
add这个符号了:
$ nm -g libtest.so 0000000000000670 T add 0000000000201030 B __bss_start w __cxa_finalize@@GLIBC_2.2.5 0000000000201030 D _edata 0000000000201038 B _end 0000000000000684 T _fini w __gmon_start__ 0000000000000540 T _init w _ITM_deregisterTMCloneTable w _ITM_registerTMCloneTable w _Jv_RegisterClasses
三、使用动态库
1. 隐式链接(编译时链接)
编写主程序main.c:#include <stdio.h>#include "so.h" int main(int argc, char *argv[]){ printf("%d\n", add(1, 2)); return 0;}
使用
gcc main.c -L. -ltest -o test进行编译。
-L:添加库文件的搜索路径
-l:指定需要链接的库。该名称是处在头lib和后缀.so中的名称,如上动态库libtest.so的l参数为-l test
此时通过
readelf test -d已经能看到生成的可执行文件test的Dynamic
section里依赖libtest.so了
$ readelf test -d Dynamic section at offset 0xe18 contains 25 entries: Tag Type Name/Value 0x0000000000000001 (NEEDED) Shared library: [libtest.so] 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] ......
dynamic symbols中也有一个undefined symbol(add)
$ nm -D test U add 0000000000601048 B __bss_start 0000000000601048 D _edata 0000000000601050 B _end 00000000004007b4 T _fini w __gmon_start__ 0000000000400578 T _init w _ITM_deregisterTMCloneTable w _ITM_registerTMCloneTable w _Jv_RegisterClasses U __libc_start_main U printf
在执行隐式链接的程序之前要注意设置
LD_LIBRARY_PATH环境变量,或者把前面生成的libtest.so复制到系统路径下,否则会找不到动态库。
$ ./test ./test: error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory $ export LD_LIBRARY_PATH=. $ ./test 3
2. 显式链接(运行时链接)
编写主程序dyn_main.c#include <stdio.h>#include <dlfcn.h> int main(int argc, char *argv[]){ void *dl = NULL; int (*add)(int a, int b); dl = dlopen( "./libtest.so", RTLD_LAZY); if( dl == NULL ) { printf("so loading error.\n"); return 1; } add = (int(*)(int, int))dlsym(dl, "add"); if( dlerror() != NULL ) { printf("fun load error.\n"); return 1; } printf("%d\n", add(1, 2)); return 0;}
使用
gcc dyn_main.c -ldl -o dyn_test编译。
这时通过
readelf dyn_test -d可以发现,dyn_test不依赖libtest.so:
$ readelf dyn_test -d Dynamic section at offset 0xe18 contains 25 entries: Tag Type Name/Value 0x0000000000000001 (NEEDED) Shared library: [libdl.so.2] 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] ......
dyn_test的dynamic symbols中也没有add:
$ nm -D dyn_test U dlerror U dlopen U dlsym w __gmon_start__ w _ITM_deregisterTMCloneTable w _ITM_registerTMCloneTable w _Jv_RegisterClasses U __libc_start_main U printf U puts
运行程序也不需要设置
LD_LIBRARY_PATH环境变量
$ ./dyn_test 3
原文出处忘了,看到烦请说一声
参考资料:
Linux动态库的编译与使用 转载
详细分析Linux动态库的使用方式
How do I list the symbols in a .so file
Import names in ELF binary
相关文章推荐
- linux编译同时链接静态和动态库
- Linux下C/C++编译链接过程及库函数使用说明
- 【linux c开发】GCC 编译链接后找不到动态库
- Linux下编译链接动态库(链接)
- linux下c++编程环境搭建,运行过程以及调试,内含C++头文件源文件编译过程链接
- linux下使用eclipse编译、链接、动态库的学习笔记
- ARM Linux编译链接过程分析
- linux-i386(ubuntu14.0)下编译安装gsoap_2.8.17过程记录
- linux下动态库静态库的简单编译和链接
- linux下g++ 编译时动态库和静态库的链接和头文件问题
- Linux静态库和动态库编译链接问题
- Linux下C语言执行过程(预处理,编译,汇编,链接,执行)
- 自己在linux上编译、链接、动态库和静态库的学习笔记
- 关于深入剖析Linux动态库链接过程的文章与资源
- ARM Linux编译链接过程分析
- linux 动态库和静态库编译链接方法
- arm-linux编译链接过程
- Red Hat 9 Linux下编译sqlite-3.3.8并在QT3.1下连接全过程详细记录
- 深入理解预编译,编译,汇编,链接的过程——之编译和使用(链接)库——动态库
- Linux下动态库和静态库的编译和链接