读取动态链接库(编译时不需要库)

一、引言

dlopen()是一个强大的库函数。该函数将打开一个新库,并把它装入内存。该函数主要用来加载库中的符号,这些符号在编译的时候是不知道的。

比如 Apache Web 服务器利用某个函数在运行过程中加载模块,这为它提供了额外的能力。一个配置文件控制了加载模块的过程。这种机制使得在系统中添加或者删除一个模块时,都不需要重新编译了。

二、函数

2.1、dlopen()

可以在自己的程序中使用 dlopen()。dlopen() 在 dlfcn.h 中定义,并在 dl 库中实现。

在dlopen函数以指定模式打开指定的动态连接库文件,并返回一个句柄给调用进程。使用dlclose来卸载打开的库。

#包含头文件: 
#include <dlfcn.h> 

# 函数定义: 
void * dlopen( const char * pathname, int mode ); 

mode:分为这两种 
RTLD_LAZY 暂缓决定,等有需要时再解出符号 
RTLD_NOW 立即决定,返回前解除所有未决定的符号。 
RTLD_LOCAL 
RTLD_GLOBAL 允许导出符号 
RTLD_GROUP 
RTLD_WORLD 

返回值: 
打开错误返回NULL 
成功,返回库引用 

编译时候要加入 -ldl (指定dl库) :
例如 :gcc test.c -o test -ldl

2.2、dlsym()

当库被装入后,可以把 dlopen() 返回的句柄作为给 dlsym() 的第一个参数,以获得符号在库中的地址。使用这个地址,就可以获得库中特定函数的指针,并且调用装载库中的相应函数。

该函数在<dlfcn.h>文件中,dlsym()的函数原型是 :

void* dlsym(void* handle,const char* symbol) 

handle是由dlopen打开动态链接库后返回的指针;
symbol就是要求获取的函数的名称;

dlsym根据动态链接库操作句柄(pHandle)与符号(symbol),返回符号对应的地址;
使用这个函数不但可以获取函数地址,也可以获取变量地址。

比如,假设在so中
定义了一个void mytest()函数,那在使用so时先声明一个函数指针:
void (*pMytest)();
然后使用dlsym函数将函数指针pMytest指向mytest函数,
pMytest = (void (*)())dlsym(pHandle, "mytest");

2.3、dlclose()

包含头文件: 
#include <dlfcn.h> 
函数原型为: 
int dlclose (void *handle); 
函数描述: 
dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0,才会真正被系统卸载。

2.4、dlerror()

包含头文件: 
#include <dlfcn.h> 
函数原型: 
const char *dlerror(void); 
函数描述: 
当动态链接库操作函数执行失败时,dlerror可以返回出错信息,返回值为NULL时表示操作函数执行成功。

三、创建与使用动态链接库

LINUX创建与使用动态链接库并不是一件难事。

编译函数源程序时选用-shared选项即可创建动态链接库,注意应以.so后缀命名,最好放到公用库目录(如/lib,/usr/lib等)下面,并要写好用户接口文件,以便其它用户共享。

使用动态链接库,源程序中要包含dlfcn.h头文件,写程序时注意dlopen等函数的正确调用,编译时要采用-rdynamic选项与-ldl选项 ,以产生可调用动态链接库的执行代码。

四、实例

库代码:

#include <stdio.h>
void hello(void)
{
    printf("hello\n");
}

编译命令:

gcc -fPIC -shared -o hello.so hello.c

使用库的代码:

#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>

int main(int argc, char **argv)
{
    void *handle;
    void (*callfun)();
    char *error;
    handle = dlopen("./hello.so",RTLD_LAZY);  //如果hello.so不是在LD_LIBRARY_PATH所申明
                                                      //的路径中必须使用全路径名
    if(!handle)
    {
        printf("%s \n",dlerror());
        exit(1);
    }
    dlerror();
    callfun=dlsym(handle,"hello");
    if((error=dlerror())!=NULL)
    {
        printf("%s \n",error);
        exit(1);
    }
    callfun();
    dlclose(handle);
    return 0;
}

编译命令:

 gcc -o hello_dlopen hello_dlopen.c -ldl

执行:./hello_dlopen

从中可以体会到编译时不需要库的好处。

另外一种在编译的时候需要动态库的使用方法:
https://blog.csdn.net/weixin_38932035/article/details/105270998

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
《Linux多线程服务端编程:使用muduo C++网络》主要讲述采用现代C++在x86-64 Linux上编写多线程TCP网络服务程序的主流常规技术,重点讲解一种适应性较强的多线程服务器的编程模型,即one loop per thread。 目 录 第1部分C++ 多线程系统编程 第1章线程安全的对象生命期管理3 1.1当析构函数遇到多线程. . . . . . . . . . . . . . . . .. . . . . . . . . . . 3 1.1.1线程安全的定义. . . . . . . . . . . . . . . . .. . . . . . . . . . . 4 1.1.2MutexLock 与MutexLockGuard. . . . . . . . . . . . . . . . . . . . 4 1.1.3一个线程安全的Counter 示例.. . . . . . . . . . . . . . . . . . . 4 1.2对象的创建很简单. . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . 5 1.3销毁太难. . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . 7 1.3.1mutex 不是办法. . . . . . . . . . . . . . . . . . . .. . . . . . . . 7 1.3.2作为数据成员的mutex 不能保护析构.. . . . . . . . . . . . . . 8 1.4线程安全的Observer 有多难.. . . . . . . . . . . . . . . . . . . . . . . . 8 1.5原始指针有何不妥. . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . 11 1.6神器shared_ptr/weak_ptr . . . . . . . . . .. . . . . . . . . . . . . . . . 13 1.7插曲:系统地避免各种指针错误. . . . . . . . . . . . . . . . .. . . . . . 14 1.8应用到Observer 上.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 1.9再论shared_ptr 的线程安全.. . . . . . . . . . . . . . . . . . . . . . . . 17 1.10shared_ptr 技术与陷阱. . . .. . . . . . . . . . . . . . . . . . . . . . . . 19 1.11对象池. . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . 21 1.11.1enable_shared_from_this . . . . . . . . . . . . . . . . . . . . . . 23 1.11.2弱回调. . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . 24 1.12替代方案. . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . 26 1.13心得与小结. . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . 26 1.14Observer 之谬. . . .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 第2章线程同步精要 2.1互斥器(mutex). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 2.1.1只使用非递归的mutex . . . . . . . . . . . . . .. . . . . . . . . . 33 2.1.2死锁. . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . 35 2.2条件变量(condition variable). . . . . . . . . .

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值