在程序编写中会使用已有的动态库,如何对这些库函数进行类打包管理,便于后面引用,这是本文要解决的问题。本文分为三步:建立一个简单的动态库、对该动态库进行类封装、测试封装的动态库。本测试在ubuntu 14.04LTS系统上完成。
1.建立一个简单的动态库
源代码如下:
头文件 fun.hpp
extern "C" int add(int a, int b);
extern "C" int sub(int a, int b);
源文件 fun.cpp
#include"fun.hpp"
//申明为extern "C"的函数不能重载,这样才能够使用dlsym进行定位加载
extern "C" int add(int a, int b)
{
return (a + b);
}
extern "C" int sub(int a, int b)
{
return (a - b);
}
源文件中的 extern "C" 关键字的使用,使得函数不能够被重载,进而下面的dlsym函数可以使用函数名称,对函数进行定位。
通过下面的命令编译生成动态库
g++ -fPIC -shared fun.cpp -o fun.so
生成的动态库文件放在当前目录下。
2. 对动态库进行封装
源代码如下:
头文件 Cfun.hpp
class Cadd
{
public:
Cadd();
~Cadd();
typedef int (*fun1)(int a, int b);
typedef int (*fun2)(int a, int b);
fun1 add; //定义函数指针成员变量
fun2 sub;
void *dlh;//保存dlopen返回的句柄
};
源文件Cfun.cpp
#include"Cfun.hpp"
#include<dlfcn.h>
#include<stdio.h>
Cadd::Cadd(): dlh(NULL)
{
if(!(dlh=dlopen("./fun.so", RTLD_LAZY)))//加载动态库
{
printf("%s\n",dlerror());
}
add = (fun1)dlsym(dlh, "add");//定位动态库中函数,并将函数指针传递给相关类成员变量
if(add == NULL)
printf("add failed\n");
sub = (fun1)dlsym(dlh, "sub");
if(sub == NULL)
printf("sub failed\n");
}
Cadd::~Cadd()
{
dlclose(dlh);//回收动态库资源
}
3.测试封装的动态库
源代码main.cpp
#include<stdio.h>
#include"Cfun.hpp"
int main(int argc, char* argv[])
{
Cadd test;
int res = test.add(2, 1);
printf("add restults: %d\n", res);
res = test.sub(2, 1);
printf("sub restults: %d\n", res);
}
通过下面的命令编译生成可执行文件
g++ -o main main.cpp Cfun.cpp -ldl
-ldl 选项是dlopen和dlsym函数依赖的库。
通过下面代码执行可执行文件 main
./main
执行结果如下:
本文展示了一种通过使用类封装动态库的方法,便于后期对动态库的管理和使用。