C语言的动态链接库
Table of Contents
1 动态链接库例子
写一个 lib.c
函数:
#include <stdio.h> int from_lib() { printf("This is hello world from lib\n"); return 0; }
再写一个调用的 main.c
函数:
#include <stdio.h> #include <stdlib.h> #include <string.h> int main(int args,char *argv[]) { from_lib(); return 0; }
对应的 Makefile
:
.PHONY:libtest a.out a.out: echo "compile a.out" gcc main.c -L. -ltest libtest: gcc lib.c -fPIC -shared -o libtest.so clean: rm -rfv libtest.so a.out
需要设置变量 LD_LIBRARY_PATH
,把当前路径加入其中然后执行:
export LD_LIBRARY_PATH="/tmp/dynamic" ./a.out
一行流执行应该这样:
LD_LIBRARY_PATH="." ./a.out
2 一个更详细的例子和说明(翻译)
有下面三个文件:
#ifndef foo_h__ #define foo_h__ extern void foo(void); #endif // foo_h__
/* ##foo.c: */ #include <stdio.h> void foo(void) { puts("Hello, I'm a shared library"); }
/* ##main.c: */ #include <stdio.h> #include "foo.h" int main(void) { puts("This is a shared library test..."); foo(); return 0; }
编译出“位置无关”代码(Position Independent Code,PIC):
$ gcc -c -Wall -Werror -fpic foo.c
基于目标文件创建一个动态链接库:
gcc -shared -o libfoo.so foo.o
把动态库和程序链接起来:
$ gcc -Wall -o test main.c -lfoo /usr/bin/ld: cannot find -lfoo collect2: ld returned 1 exit status
报错表示编译器找不到对应的库文件。需要使用
-L
参数来告诉编译器 到哪儿找对应的动态库文件。$ gcc -L. -Wall -o test main.c -lfoo
使运态库在运行时能被找到。
$ ./test ./test: error while loading shared libraries: libfoo.so: cannot open shared object file: No such file or directory
出现该错误说明该动态库找不到。
可以通过设置
LD_LIBRARY_PATH
变量解决该问题:$ export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH $ ./test This is a shared library test... Hello, I'm a shared library
还可以在编译的时候通
-rpath
指定一个固定的地址:$ unset LD_LIBRARY_PATH $ gcc -L. -Wl,-rpath=. -Wall -o test main.c -lfoo $ ./test This is a shared library test... Hello, I'm a shared library
还可以把编译生成的
so
文件放到系统动态库默认目录中/usr/lib
和/usr/local/lib
。然后更新一下动态库的cache即可。$ cp /home/username/foo/libfoo.so /usr/lib $ chmod 0755 /usr/lib/libfoo.so $ ldconfig
检查一下cache里面有没有:
$ ldconfig -p|grep foo libfoo.so (libc6) => /usr/lib/libfoo.so
还可以再使用
ldd
来查看一下可执行文件test
中依赖的是哪一个库:$ ldd test | grep foo libfoo.so => /usr/lib/libfoo.so (0x00a42000)
这下再重新来试一次:
$ unset LD_LIBRARY_PATH $ gcc -Wall -o test main.c -lfoo $ ldd test | grep foo libfoo.so => /usr/lib/libfoo.so (0x00a42000) $ ./test This is a shared library test... Hello, I'm a shared library