Linux下C++动态库的生成和使用
来源:互联网 发布:负面情绪 知乎 编辑:程序博客网 时间:2024/04/30 11:00
1. 导出函数的动态库
//DllTest.h#ifndef _DLLTEST_H#define _DLLTEST_Hextern "C" int add(int a,int b);typedef int (*add_t)(int a,int b);#endif//DllTest.cc#include "DllTest.h"int add(int a,int b){return a+b;}上述动态库需要导出函数add。编译生成动态库:g++ -fPIC -shared -o libDllTest.so DllTest.cc
动态库加载方式分为静态和动态加载。
静态方式加载动态库示例:
//main.cc#include <iostream>using namespace std;#include "DllTest.h"int main(int argc,char** argv){cout << "------------static call-------------" << endl;cout << "add(5,3) = " << add(5,3) << endl;}编译可执行程序:g++ -o main main.cc -lDllTest -L. /
动态方式加载动态库示例:
//main.cc#include <iostream>using namespace std;#include <dlfcn.h> #include "DllTest.h"int main(int argc,char** argv){cout << "------------dynamic call-------------" << endl;void *so_handle = dlopen("libDllTest.so", RTLD_LAZY); // 载入.so文件 if (!so_handle) { cout << "Error: load so `failed." << endl; return -1; } add_t fn = (add_t)dlsym(so_handle, "add"); // 载入函数 if (NULL == fn) { cout << "get function address failed" << endl; return -1; } cout << "add 57 + 3 = " << fn(57, 3) << endl; // 调用函数 dlclose(so_handle); // 关闭so句柄 }编译可执行程序:g++ -o main main.cc -ldl
extern “C”的作用不用多说了,但是需要说明的一点是:静态加载方式下可以不需要这个,但是动态加载方式下是必需的。
即使两种加载方式编译时都顺利通过,在运行时仍然可能出现找不到库的情况,此时静态方式会提示类似“./main: error while loading shared libraries: libDllTest.so: cannot open shared object file: No such file or directory”这样的错误,动态方式会导致so_handle为空。此时可通过两种方法解决这个问题:
- export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./,假设动态库文件与可执行文件在同一目录下
- 修改/etc/ld.so.conf文件,增加动态库所在目录,然后执行/sbin/ldconfig即可。
2. 导出类的动态库
Linux下动态库中导出类比较麻烦,可参考下例进行。说明一下,这个例子参考了http://blog.chinaunix.net/uid-26000296-id-3778641.html,代码略作了修改。
//Base.h#ifndef BASE_CLASS_H#define BASE_CLASS_Hclass BaseClass {protected:int member_var;public:BaseClass(): member_var(0) {}virtual ~BaseClass() {}void set_member_var(int param) {member_var = param;}virtual int get_member_var() const = 0;};// the types of the class factoriestypedef BaseClass* create_t();typedef void destroy_t(BaseClass*);#endif//SubClass.cc#include "Base.h"class SubClass : public BaseClass {public:virtual int get_member_var() const {return member_var;}};// the class factoriesextern "C" BaseClass* create() {return new SubClass;}extern "C" void destroy(BaseClass* p) {delete p;}编译生成动态库:g++ -fPIC -shared -o libSubClass.so SubClass.cc
加载动态库示例代码:
//main.cc#include <iostream>using namespace std;#include <dlfcn.h> #include "Base.h"int main(int argc,char** argv){void *so_handle = dlopen("libSubClass.so", RTLD_LAZY); // 载入.so文件 if (!so_handle) { cout << "Error: load so failed." << endl; return -1; } create_t* create = (create_t*)dlsym(so_handle, "create"); // 载入函数 if (NULL == create) { cout << "get function address failed" << endl; return -1; } destroy_t* destroy = (destroy_t*) dlsym(so_handle, "destroy");if (NULL == destroy) { cout << "get function address failed" << endl; return -1; } BaseClass* pObj = create();pObj->set_member_var(10);cout << "pObj->get_member_var():" << pObj->get_member_var() << endl;destroy(pObj);dlclose(so_handle); // 关闭so句柄 }编译可执行程序:g++ -o main main.cc -ldl。很明显,上述代码采用了动态加载方式。其实导出类的动态库也可以采用静态加载方式,示例代码如下:
//Base.h#ifndef BASE_CLASS_H#define BASE_CLASS_Hclass BaseClass {protected:int member_var;public:BaseClass(): member_var(0) {}virtual ~BaseClass() {}void set_member_var(int param) {member_var = param;}virtual int get_member_var() const = 0;};// the types of the class factoriestypedef BaseClass* create_t();typedef void destroy_t(BaseClass*);#endif//SubClass.h#include "Base.h"class SubClass : public BaseClass {public:SubClass(){};virtual ~SubClass(){};virtual int get_member_var() const;};// the class factoriesextern "C" BaseClass* create() {return new SubClass;}extern "C" void destroy(BaseClass* p) {delete p;}//SubClass.cc#include "SubClass.h"int SubClass::get_member_var() const {return member_var;}编译生成动态库:g++ -fPIC -shared -o libSubClass.so SubClass.cc
静态加载示例代码如下:
//main.cc#include <iostream>using namespace std;#include <dlfcn.h> #include "SubClass.h"int main(int argc,char** argv){BaseClass* pObj = create();pObj->set_member_var(10);cout << "pObj->get_member_var():" << pObj->get_member_var() << endl;destroy(pObj);}编译可执行程序:g++ mainClass.cc -o mainClass -L./ -lSubClass
个人觉得静态加载方式明显的比动态加载方式麻烦,而且通用性不好,所以不建议使用。
上述代码中需要注意一个细节问题:如果SubClass.h中不定义、只声明SubClass的析构函数,虽然生成动态库时不会出错,但是生成可执行文件时,会报下列类似错误:
In function `SubClass::SubClass()':
mainClass.cc:(.text._ZN8SubClassC2Ev[_ZN8SubClassC5Ev]+0x1f): undefined reference to `vtable for SubClass'
这个错误是一个比较常见的错误,一般原因都是由于在继承层次的类中,virtual函数没有定义、只有声明。比如上例中的Base.h中,如果BaseClass的析构函数如果缺失定义,也会出现类似错误。
- linux下C的动态库生成和调用
- linux下Eclipse进行C编程时动态链接库的生成和使用
- Linux下动态库生成和使用
- linux下生成和使用动态库
- Linux下动态库生成和使用
- Linux 下 动态链接库 .so 的生成和使用
- Linux下动态库的生成和使用
- Linux下动态库的生成和使用
- Linux下C++动态库的生成和使用
- Linux下动态库的生成和使用
- Linux下动态库的生成和使用
- Linux下动态库的生成和使用
- linux下动态库的生成和使用
- 【ARM-Linux开发】linux下Eclipse进行C编程时动态链接库的生成和使用
- Linux下c和cuda混合编译,并生成动态链接库.so和使用
- Linux下c和cuda混合编译,并生成动态链接库.so和使用
- Linux下c和cuda混合编译,并生成动态链接库.so和使用
- linux 动态库的生成和使用
- STL中优先队列的使用方法
- 表单重复提交
- jsp连接mysql数据库
- (阶段三 dijkstra1.4)HDU 1596 find the safest road(最短路的变形题:求乘积,求最大值)
- EL表达式语言
- Linux下C++动态库的生成和使用
- 数论基础练习赛-解题报告
- John
- 碎片攻击
- C++中引用和指针的区别
- opencv学习_12 (harris角点检测)
- 你肯定不知道的科技界九位同性恋领袖
- 15.IO(四)【IO包的其他类】
- FZU 1977 Pandora adventure 解题报告(插头DP)