《学习Linux编程的心路历程》1动态链接库

1196阅读 0评论2012-04-27 zxc381219
分类:LINUX

1、如何整出自己的动态库:

    我们可以看到 /lib /usr/lib 文件夹里面有很多.so后缀的文件,so其实是shared object file的缩写,这些都是动态链接库啦,什么是动态链接库和静态库函数库呢,静态函数库就是指:当应用程序道目标代码与函数库进行链接时,函数库中被引用的代码将被复制到最终生成的可执行文件中。而动态链接库,链接二字,顾名思义,使用它时不是真正的使用它本身而是动态的使用它的链接(文件路径,文件名,函数名)
    如何编译动态库:关键参数 -fPIC  , gcc -fPIC -c xxx.c
    如何链接成动态库:关键参数 -shared ,  gcc -shared -o libxxx.so xxx.o
    如何鉴别动态库:可以使用file命令 ,动态库会输出类似信息 "ELF 32-bit LSB shared object"
    好,我们来创建一个吧 。

点击(此处)折叠或打开

  1. root@zxc-Lenovo:/home/zxc/work# cat hello.c
  2. #include "stdio.h"

  3. void hello()
  4. {
  5.   printf("hello world!\n");
  6. }
  7. root@zxc-Lenovo:/home/zxc/work#
root@zxc-Lenovo:/home/zxc/work# gcc -fPIC -c hello.c
root@zxc-Lenovo:/home/zxc/work# gcc -shared -o libhello.so hello.o
root@zxc-Lenovo:/home/zxc/work# file libhello.so
libhello.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, not stripped

2、整出了自己的动态库,如何使用它:
    首先,编译链接自己的程序时,需要引用到我们的动态库,gcc 提供了-L参数和-l参数来分别代表动态库的路径以及文件名。
   

点击(此处)折叠或打开

  1. #include "stdio.h"

  2. void main()
  3. {
  4.     hello();
  5. }
    gcc test.c -lhello -L. -o test
    编译之后运行./test 发现竟然报错! error while loading shared libraries: libhello.so: cannot open shared object file: No such file or directory  ,咦,怎么回事?原来虽然链接时链接器(dynamic linker)找到了动态库libhello.so,但动态加载器(dynamic loader, 一般是/lib/ld-Linux.so.2)却没找到。
    别急,有两种办法,1、直接把libhello.so放入 /lib /usr/lib 2、把当前路径加入

点击(此处)折叠或打开

  1. root@zxc-Lenovo:/home/zxc/work# cat hello2.c
  2. #include "stdio.h"

  3. void hello()
  4. {
  5.   printf("hello world!\n");
  6. }
  7. root@zxc-Lenovo:/home/zxc/work#
    根据ld函数规则,创建下面的test.c

点击(此处)折叠或打开

  1. root@zxc-Lenovo:/home/zxc/work# cat test.c
  2. #include "stdio.h"
  3. #include "dlfcn.h"

  4. void main()
  5. {
  6.     void *handle;
  7.     void (*fuc)(void);
  8.  
  9.     handle=dlopen("/home/zxc/work/libhello2.so",RTLD_NOW);
  10.     
  11.     fuc = dlsym(handle,"hello");
  12.     fuc();

  13.     dlclose(handle);
  14.     
  15.      
  16. }
    编译时注意-ldl选项:gcc test.c -ldl -o test2  ,这里看到我们并没有指定动态库的路径和名称,看起来跟hello2的动态库没有任何关系,实际上动态库的调用完全是在代码中实现。
    编译完成后运行仍然得到正确的结果,
root@zxc-Lenovo:/home/zxc/work# ./test2
hello world!

    4、两种调用动态库的方式,你会选择哪一种呢??

上一篇:今天开始在Ubuntu Firefox环境更新博客 《学习Linux编程的心路历程》
下一篇:自己的问题自己回答 , 呃,三年后的回答。。