Chinaunix首页 | 论坛 | 博客
  • 博客访问: 34051
  • 博文数量: 11
  • 博客积分: 355
  • 博客等级: 二等列兵
  • 技术积分: 160
  • 用 户 组: 普通用户
  • 注册时间: 2011-05-07 18:18
文章分类
文章存档

2012年(11)

分类: LINUX

2012-04-27 23:25:23

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、两种调用动态库的方式,你会选择哪一种呢??

阅读(1163) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~