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

来源:互联网 发布:三体 圣母 知乎 编辑:程序博客网 时间:2024/04/30 09:40

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 (未细读,可能不相关)


原创粉丝点击