Linux共享库技术是一项很激动人心的技术,它充分提供了程序的动态扩展能力,能够方便的进行Linux下程序的插件式开发。而且在运行过程中,如果需求有更改,只需要更新相应的共享库,从而能很方便的实现功能的无缝切换,极大的提供了程序的动态扩展能力。下面将说明动态库的开发方式。
1、支持动态库的主程序的开发:
在使用dl系列接口时,需要包含头文件 #include <dlfcn.h>
a).调用dlopen函数打开到共享库的操作句柄;
函数接口为: void *dlopen(const char *filename, int flag); filename为使用的动态库的文件所在的路径,一般扩展名为.so;
b).调用dlsym函数从共享库符号中获取对应的操作接口和操作对象数据;
函数接口为: void *dlsym(void *handle, const char *symbol); symbol为查找的符号,handle为上面打开的共享库操作句柄;返回结果为共享库中实现的接口;
c).调用dlcose函数关闭共享库操作句柄:
函数接口为: int dlclose(void *handle); 关闭打开的文件句柄;
d).在上面的3个函数调用后,可以使用 char *dlerror(void); 函数去查询共享库操作中出现的错误;
2、动态库的开发:
共享库中只需要实现主程序中需要操作的接口即可,主要需要注意以下的事项:
a).共享库对外提供接口的头文件中必须使用 extern "C" 包含起来,否则执行时会出现segment fault;
b).在共享库操作接口中打开的对象等资源必须在关闭共享库操作句柄之前释放,否则会出现segment fault;
c).共享库的链接只需要在gcc中增加 -shared 选项;
下面是一个例子:
主执行程序:main.cpp
#include
#include
#include "SMSGamePlugin.h"
int main(int argc, char** argv)
{
void *GameLib = dlopen("./Flower.so", RTLD_LAZY);
const char *dlError = dlerror();
if (dlError)
{
std::cout << "dlopen error!" << dlError << std::endl;
return(-1);
}
CSMSGamePlugin *(*pGetGameObject)(void);
pGetGameObject = (CSMSGamePlugin *(*)(void))dlsym(GameLib, "GetGameObject");
dlError = dlerror();
if (dlError)
{
std::cout << "dlsym error!" << dlError << std::endl;
return(-1);
}
CSMSGamePlugin *pGame = (*pGetGameObject)();
pGame->Initialize();
pGame->Load();
pGame->Handle();
delete *pGame;
dlclose(GameLib);
}
公用基类部分:SMSGamePlugin.h
#ifndef __SMSGamePlugin_h__
#define __SMSGamePlugin_h
class CSMSGamePlugin
{
public:
virtual int Initialize(void) = 0;
virtual int Load(void) = 0;
virtual int Handle(void) = 0;
};
#endif
编译:g++ -rdynamic -ldl -s -o Test main.cpp
共享库部分:
共享库头文件:Flower.h
#ifndef __Flower_h__
#define __Flower_h__
#include "SMSGamePlugin.h"
extern "C" CSMSGamePlugin *GetGameObject(void);
class CFlower: public CSMSGamePlugin
{
public:
virtual int Initialize(void);
virtual int Load(void);
virtual int Handle(void);
};
#endif
共享库实现文件:Flower.cpp
#include
#include "Flower.h"
CSMSGamePlugin *GetGameObject(void)
{
return(new CFlower());
}
int CFlower::Initialize(void)
{
std::cout << "Initialize()" << std::endl;
return(0);
}
int CFlower::Load(void)
{
std::cout << "Load()" << std::endl;
return(0);
}
int CFlower::Handle(void)
{
std::cout << "Handle()" << std::endl;
return(0);
}
编译:
g++ -c Flower.cpp
g++ -shared -o Flower.so
注意:
如果不加extern "C"编译后运行时就会提示:
dlsym error!./Test: undefined symbol: GetGameObject