linux c++动态链接库so编写
2015-06-04 11:00
441 查看
Linux下的动态链接库是.so文件,即:Shared Object,下面是一个简单的例子说明如何写.so以及程序如何动态载入.so中的函数和对象。
testso.h:
testso.cpp:
编译so:
注意,-shared参数和-fPIC参数非常重要:
-shared 告诉gcc要生成的是动态链接库;
-fPIC 告诉gcc生成的生成的代码是非位置依赖的,方面的用于动态链接。
在主程序里调用这个动态链接库:
main.cpp:
编译主程序:
g++ main.cpp -o main -ldl
注意:要加上-ldl
好了,上面就是如何写和调用动态库中的C函数。
对于C++中的类,不能直接导出,需要通过继承的方式才能从动态链接库中导出:
=====================
testso.h:
testso.cpp:
main.cpp: // 这里需要注意
testso.h:
<span style="font-size:14px;">#ifndef _TESTSO_H #define _TESTSO_H extern "C" { int myadd(int a, int b); typedef int myadd_t(int, int); // myadd function type } #endif // _TESTSO_H </span>
testso.cpp:
<span style="font-size:14px;">#include "testso.h" extern "C" int myadd(int a, int b) { return a + b; } </span>
编译so:
<span style="font-size:14px;">g++ -shared -fPIC -o testso.so testso.cpp</span>
注意,-shared参数和-fPIC参数非常重要:
-shared 告诉gcc要生成的是动态链接库;
-fPIC 告诉gcc生成的生成的代码是非位置依赖的,方面的用于动态链接。
在主程序里调用这个动态链接库:
main.cpp:
<span style="font-size:14px;">#include #include // for dynamic library函数 #include "testso.h" void print_usage(void) { printf("Usage: main SO_PATH/n"); } int main(int argc, char *argv[]) { if (2 != argc) { print_usage(); exit(0); } const char *soname = argv[1]; void *so_handle = dlopen(soname, RTLD_LAZY); // 载入.so文件 if (!so_handle) { fprintf(stderr, "Error: load so `%s' failed./n", soname); exit(-1); } dlerror(); // 清空错误信息 myadd_t *fn = (myadd_t*)dlsym(so_handle, "myadd"); // 载入函数 char *err = dlerror(); if (NULL != err) { fprintf(stderr, "%s/n", err); exit(-1); } printf("myadd 57 + 3 = %d/n", fn(57, 3)); // 调用函数 dlclose(so_handle); // 关闭so句柄 return 0; } </span>
编译主程序:
g++ main.cpp -o main -ldl
注意:要加上-ldl
好了,上面就是如何写和调用动态库中的C函数。
对于C++中的类,不能直接导出,需要通过继承的方式才能从动态链接库中导出:
=====================
testso.h:
<span style="font-size:14px;">#ifndef _TESTSO_H #define _TESTSO_H // 只能通过基类调用,因此需要先定义一个基类,然后在create中生成真正需要生成的对象。 class Base { public: int a, b; virtual int add(void) { return -1; } }; class A : public Base { public: int add(void); }; extern "C" { Base* create(void); void destroy(Base *p); typedef Base* create_t(void); // create factory typedef void destory_t(Base*); // destory } #endif // _TESTSO_H </span>
testso.cpp:
<span style="font-size:14px;">#include "testso.h" int A::add(void) { return a + b; } extern "C" { Base* create(void) // 注意:create函数必须返回Base的对象,不能直接返回A的 // 对象,否则后面调用A::add()的时候会提示错误。 { return new A; } void destory(Base *p) { if (p) delete p; } } </span>
main.cpp: // 这里需要注意
<span style="font-size:14px;">#include #include #include #include "testso.h" void print_usage(void) { printf("Usage: myso SO_PATH/n"); } int main(int argc, char *argv[]) { if (2 != argc) { print_usage(); exit(0); } const char *soname = argv[1]; void *so_handle = dlopen(soname, RTLD_LAZY); if (!so_handle) { fprintf(stderr, "Error: load so `%s' failed./n", soname); exit(-1); } dlerror(); create_t *create = (create_t*) dlsym(so_handle, "create"); if (NULL != err) { fprintf(stderr, "%s/n", err); exit(-1); } Base *pa = create(); pa->a = 57; pa->b = 3; printf("A.add(57, 3)=%d/n", pa->add()); // 注意,这里通过虚函数实现了 // 对A::add()的调用。 destory_t *destory = (destory_t*) dlsym(so_handle, "destory"); if (NULL != err) { fprintf(stderr, "%s/n", err); exit(-1); } destory(pa); pa = NULL; dlclose(so_handle); printf("DONE!/n"); return 0; } </span>
相关文章推荐
- 一步步学习Linux多任务编程
- centos桌面使用
- CentOS 6.5 图文安装教程
- 安装CentOS 7 出错BootLoaderError
- centos下 安装jdk
- Linux多线程同步的几种方式
- linux驱动之模块化编程
- 六种在 Linux 上为你带来 iTunes 般体验的方法
- Linux下查找目录或文件
- Linux 设备模型基本概念 (一)
- Linux安装R语言包
- 转载: linux下创建svn代码库
- linux下查看和添加PATH环境变量
- linux定时任务crontab详解
- linux移植过程中近日遇到问题汇总贴
- Linux 文件系统
- CentOS6.3 重启后/etc/resolv.conf被还原解决办法
- wpa_supplicant_8_ti hostapd wpa_supplicant TI 官方的wpa_supplicant hostapd 移植到linux
- Linux 命令笔记(1)
- linux程序分析工具介绍(二)—-ldd,nm