linux下动态链接库的使用-dlopen dlsym dlclose dlerror

source: http://www.eifr.com/article.php?id=1766&page=2

Linux下的dlopen、dlsym、dlclose 相当于windows平台的LoadLibrary、GetProcAddress 、FreeLibrary,可以在运行时动态加载动态库,使用其中的导出函数。但是局限在于,这样仅仅能够导出全局函数,而不能导出类的方法。所以一般动态库导出C++类实现的功能时都会设计一大堆的全局函数来包装一下。比如(伪代码)

class A{
public:
      int run(...){...};
}

导出函数及使用可能会是:

//导出函数
handle_type AOpen(parameters...);
int ARun(handle_type handle, parameters...);
void AClose(handle_type handle);

//使用时可能是:
handle_type AHandle = -1;
AHandle = AOpen(....);     //获取句柄,即在AOpen中实例化一个A对象
ARun(AHandle, ....);        //句柄亦做为参数,即通过句柄在内部找到由AOpen生成的实例
AClose(AHandle);            //通过句柄释放先前生成的对象

//内部原理:动态库内部维护一张表(句柄与A类一一对应),
//             每次AOpen都生成新A对象和新AHandle,放入
//             内部表, 以后调用此A对象的方法时,都需要通过
//             句柄先在内部映射表中找到对象。

这多少有些郁闷吧,要是能直接像动态连接一样使用类多好。比如一拿到A.so直接new A()就能用。可是这是不行的,dlopen仅能导入函数,并且是c风格的名字类型。

C++ dlopen mini HOWTO里给了一种折中方案,就是通过导出“创建类的函createA数”和“释放类的函数releaseA”来使用动态库中的类,这和模式设计中的工厂模式是一样的。

具体的做法是:
1. 准备一份头文件,加入一个纯虚父类ABase,并声明createA,releaseA;
2. 在生成A.so的实现源码中,写业务类AHello,继承ABase,并导出上面提到的两个函数createA,releaseA;
3. 需要使用A.so的代码,使用dlopen打开so文件,dlsym导入createA,releaseA, 调用createA返回ABase指针类型的实际是AHello类型的实例,便可以使用这个AHello类实例了;
4. 调用raleaseA释放AHello实例。

注意:
1. 基类是必须是,不然编译器怎么在编译的时候知道AHello的实现在哪里?
2. 函数导入出需要加上extern “C”防止导出名字被修改。

如此一来,使用某个导出类的动态库*.so,只要拿到它的父类声明就可以dlopen动态导入了,可以实现下面形式的调用。

int main()
{
    void *dl  = load_so("./a.so");
    test_so(dl);

    dl  = load_so("./b.so");
    test_so(dl);

    dl  = load_so("./c.so");
    test_so(dl);
    return 0;
}

示例代码:exportclass

参考:
1. http://www.faqs.org/docs/Linux-mini/C++-dlopen.html
2. http://www.codeproject.com/KB/cpp/howto_export_cpp_classes.aspx (未细读,可能不相关)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值