Linux下创建动态库与使用

参考文章:dll和so文件区别与构成:http://www.cnblogs.com/likwo/archive/2012/05/09/2492225.html

动态库路径配置- /etc/ld.so.conf文件:http://blog.csdn.net/blade2001/article/details/32839937

 

1.如何生成一个动态库:

假设有4个文件(1个头文件,3个.c源文件)so_test.h、test_a.c、test_b.c、test_c.c。我们将这几个文件编译成一个动态库:libtest.so。

so_test.h:
 
#include <stdio.h>
#include <stdlib.h>
void test_a();
void test_b();
void test_c();
 
test_a.c:
 
#include "so_test.h"
void test_a()
{
    printf("this is in test_a...\n");
}
 
test_b.c:
 
#include "so_test.h"
void test_b()
{
    printf("this is in test_b...\n");
}
 
test_c.c:
 
#include "so_test.h"
void test_c()
{
    printf("this is in test_c...\n");
}
 
将这几个文件编译成一个动态库:libtest.so
$ gcc test_a.c test_b.c test_c.c -fPIC -shared -o libtest.so
2、动态库的链接
 
在1、中,我们已经成功生成了一个自己的动态链接库libtest.so,下面我们通过一个程序来调用这个库里的函数。程序的源文件为:test.c。
test.c:
 
#include "so_test.h"
int main()
{
    test_a();
    test_b();
    test_c();
    return 0;
 
}
l         将test.c与动态库libtest.so链接生成执行文件test:
$ gcc test.c -L. -ltest -o test
 
l         测试是否动态连接,如果列出libtest.so,那么应该是连接正常了
 
$ ldd test
l         执行test,可以看到它是如何调用动态库中的函数的。
但是此时出现以下问题:

$>ldd test
linux-gate.so.1 => (0xb77c6000)
libtest.so => not found//动态库未找到
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb75ea000)
/lib/ld-linux.so.2 (0xb77c7000)

但是查看当前目录下明明有动态库呀。

$>ls -l
总用量 36
-rwxrwxr-x 1 burgess burgess 6992 Dec 6 16:58 libtest.so
-rw-rw-r-- 1 burgess burgess 249 Dec 6 16:54 so_test.h
-rwxrwxr-x 1 burgess burgess 7372 Dec 6 17:00 test
-rw-rw-r-- 1 burgess burgess 189 Dec 6 16:55 test_a.c
-rw-rw-r-- 1 burgess burgess 189 Dec 6 16:56 test_b.c
-rw-rw-r-- 1 burgess burgess 209 Dec 6 17:00 test.c
-rw-rw-r-- 1 burgess burgess 189 Dec 6 16:57 test_c.c

执行./test却出错!

./test
./test: error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory

错误提示动态库里没有这个文件。

 

动态装入器负责装入动态链接的可执行程序运行所需的共享库(shared library,即动态库)。

ld.so.conf 文件包含一个所有目录(/lib 和 /usr/lib 除外,它们会自动包含在其中)的清单,动态装入器将在其中查找共享库。

 

那么此时我们就需要把这个文件的路径加入ld.so.conf 文件里了。

最省事的办法就是通过/etc/ld.so.conf文件来指定动态库的目录(需要有root权限)。

#vi  /etc/ld.so.conf 

里面显示:

include /etc/ld.so.conf.d/*.conf
 /usr/local/lib

这里的“/usr/local”就是默认的动态库路径了。我们想要添加自己的路径再起一行加入就OK。j假设“libtest.so”所在路径是:“/home/burgess/gitlearn/test”

那么添加进去就变成了

include /etc/ld.so.conf.d/*.conf
 /usr/local/lib
/home/burgess/gitlearn/test

但是加进去了,退回到当前用户再去$>ldd test还是显示libtest.so => not found。

原来在动态装入器能“看到”这一信息之前,必须将它转换到 ld.so.cache 文件中。可以通过运行 ldconfig 命令做到这一点:

#ldconfig

另外,要查看 ldconfig 可以“看到”的所有共享库,输入:  

# ldconfig -p | less

就可以查看libtest.so是否在显示的库列表里了。

 

 

最后,再执行:

$>ldd test

显示动态库就找到了:

linux-gate.so.1 => (0xb77dc000)
libtest.so => /home/burgess/gitlearn/test/libtest.so (0xb77b8000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb75fd000)
/lib/ld-linux.so.2 (0xb77dd000)

 

(下面这段话是照第二篇文章搬过来的,大家别拿板砖砸我。)

还有另一个方便的技巧可以用来配置共享库路径。有时候希望告诉动态装入器在尝试任何 /etc/ld.so.conf 路径以前先尝试使用特定目录中的共享库。在运行的较旧的应用程序不能与当前安装的库版本一起工作的情况下,这会比较方便。

LD_LIBRARY_PATH

要指示动态装入器首先检查某个目录,请将 LD_LIBRARY_PATH 变量设置成您希望搜索的目录。多个路径之间用冒号分隔;例如:

# export LD_LIBRARY_PATH="/usr/lib/old:/home/burgess/gitlearn/test/lib"

导出 LD_LIBRARY_PATH 后,如有可能,所有从当前 shell 启动的可执行程序都将使用 /usr/lib/old 或 /opt/lib 中的库,如果仍不能满足一些共享库相关性要求,则转回到 /etc/ld.so.conf 中指定的库。

posted @ 2016-12-06 18:26  弗莱曼飞侠  阅读(701)  评论(0编辑  收藏  举报