Linux下动态链接库的使用

Linux下的静态链接库,做起来比较容易,只要将目标文件用ar打包就可以,下面写一下动态链接库的制作和使用方法,完全是根据个人理解和经验总结,有不对的地方还请大家指正。

动态链接库的生成:

代码上与写静态链接库没什么区别,主要是在编译时,以两个文件举例:

复制代码
/* mylib.h */
void  Print();

/* mylib.c */
#include 
< stdio.h >
#include 
" mylib.h "

void  Print()
{
    printf(
" This is in mylib\n " );
}
复制代码

编译方法如下:

gcc -fpic -shared mylib.c -o mylib.so

此时将生成mylib.so动态链接库文件。

动态链接库在使用时,分为“隐式调用”和“显式调用”两种,如果是隐式调用,则与静态库的使用方法差不多,注意需要包含导出函数的头文件,即mylib.h:

复制代码
#include  < stdio.h >
#include 
" mylib.h "

int  main()
{
    Print();
}
复制代码

编译方法:

gcc -o main main.c -L./ mylib.so

注意要加上动态链接库的搜索路径,否则编译器只会到系统路径中去寻找。

显式调用的方式,不必包含mylib.h,但是需要增加几个系统调用:

复制代码
#include  < stdio.h >
#include 
< dlfcn.h >   //  显式加载需要用到的头文件

int   main()
{
    
void   * pdlHandle  =  dlopen( " ./mylib.so " , RTLD_LAZY);  //  RTLD_LAZY 延迟加载
     char   * pszErr  =  dlerror();
    
if ! pdlHandle  ||  pszErr )
    {
        printf(
" Load mylib failed!\n " )
        
return   1 ;
    }

    
void  ( * Print)()  =  dlsym(pdlHandle,  " Print " );  //  定位动态链接库中的函数
     if ! Print )
    {
        pszErr 
=  dlerror();
        printf(
" Find symbol failed!%s\n " , pszErr);
        dlclose(pdlHandle);
        
return   1 ;
    }

    Print(); 
//  调用动态链接库中的函数

    dlclose(pdlHandle); 
//  系统动态链接库引用数减1

    
return   0 ;
}
复制代码

 

可以看到,显式调用的代码看上去要复杂很多,但是却比隐式调用要灵活,我们不必在编译时就确定要加载哪个动态链接库,可以在运行时再确定,甚至重新加载。

看一下显式调用的编译方式:

gcc -ldl -o main main.c

注意要添加-ldl选项,以使用显式调用相关的函数调用。

 

/****************************************************这是一条分割线************************************/

 

2.2  动态调用,使用dl系列函数,完成对动态库函数的调用。

2.2.1 重要的dlfcn.h头文件
    LINUX下使用动态链接库,源程序需要包含dlfcn.h头文件,此文件定义了调用动态链接库的函数的原型。

2.2.2 dlerror
    原型为: const char *dlerror(void);
    当动态链接库操作函数执行失败时,dlerror可以返回出错信息,返回值为NULL时表示操作函数执行成功。

2.2.3 dlopen
    原型为: void *dlopen (const char *filename, int flag);
    dlopen用于打开指定名字(filename)的动态链接库,并返回操作句柄。
filename: 如果名字不以/开头,则非绝对路径名,将按下列先后顺序查找该文件。
    (1) 用户环境变量中的LD_LIBRARY_PATH值;
    (2) 动态链接缓冲文件/etc/ld.so.cache
    (3) 目录/lib,/usr/lib
flag表示在什么时候解决未定义的符号(调用)。取值有两个:
    1) RTLD_LAZY : 表明在动态链接库的函数代码执行时解决。
    2) RTLD_NOW : 表明在dlopen返回前就解决所有未定义的符号,一旦未解决,dlopen将返回错误。
    dlopen调用失败时,将返回NULL值,否则返回的是操作句柄。

2.2.4 dlsym : 取函数执行地址
    原型为: void *dlsym(void *handle, char *symbol);
    dlsym根据动态链接库操作句柄(handle)与符号(symbol),返回符号对应的函数的执行代码地址。由此地址,可以带参数执行相应的函数。
如程序代码: void (*print_func)(char *buf); /* 说明一下要调用的动态函数print_func*/
    print_func=dlsym("libfunc.so","print"); /* 打开libfunc.so共享库,取print函数地址 */
    print_func("John"); /* 调用print_func函数 */

2.2.5 dlclose : 关闭动态链接库
    原型为: int dlclose (void *handle);
    dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。

 

2.3
执行程序时若出现error while loading shared libraries: libfunc.so: cannot open shared object file: No such file or directory

很明显,是动态库的路径不正确,编译时用-L指定的库文件路径,在执行文件时不起作用了.怎样让可执行文件找到我们自己建立的库呢?这里有几种方法:

( a ) 将库文件libfunc.so拷贝到/usr/lib 或 /lib 或 /usr/local/lib下,默认情况下,系统从这几个地方寻找库文件.
( b ) 导出 符号LD_LIBRARY_PATH,如export  LD_LIBRARY_PATH=/apps/src/demo/如果有多条路径,用 ‘:’ 分割.
( c ) 将库文件的路径添加到 /etc/ld.so.conf 中去,并执行/sbin/ldconfig
( d )在编译链接时添加选项目 -Wl,--rpath指定,如:gcc -Wl,--rpath,/apps/src/demo/ -L/apps/src/demo/ test.c -lfunc -o test 或者 gcc -Wl,--rpath -Wl,/apps/src/demo/ -L/apps/src/demo/ test.c -lfunc -o test


补充:查看文件使用的动态库用ldd命令.

 

转自:http://www.cnblogs.com/Xiao_bird/archive/2010/03/01/1675821.html
        http://www.rosoo.net/a/201101/10780.html
还可参考:http://blog.csdn.net/jenshy/article/details/674621

转载于:https://www.cnblogs.com/zjfdbz/archive/2013/03/04/2943463.html

  • 0
    点赞
  • 0
    收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:编程工作室 设计师:CSDN官方博客 返回首页
评论
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值