经过几个小时的研究,我什么也没发现,所以我向你们求助,希望能找到解决办法。我将用c++编写一个机器人,并希望在某个时候为它制作一个插件系统。现在我知道我可以为它编写一种脚本语言,但是,我知道只需要编写一个api并在运行时动态地拥有到它的程序链接就可以了。我的问题是,我如何获得动态链接(就像十六进制的插件)?是否有任何优雅的解决方案,或至少在典型的设计理论?
发布于 2014-10-31 10:39:33
在Linux系统上,您希望使用dlopen(3) & dlsym (或者一些封装这些函数的库,例如来自GTK、Qt、波科等的滑翔 )。更准确地说,
构建一个位置独立码共享库作为插件:
gcc -fPIC -Wall -c plugin1.c -o plugin1.pic.o
gcc -fPIC -Wall -c plugin2.c -o plugin2.pic.o注意,如果插件是用C++编写的,您将用g++编译它,您应该将插件函数声明为extern "C",以避免使用名称残缺。
然后将您的插件链接为
gcc -shared -Wall plugin1.pic.o plugin2.pic.o -o plugin.so您可以添加动态库(例如,如果您的插件想要GNU,请在上面命令的末尾添加一个-lreadline )。
最后,在您的主程序中调用具有完整路径的dlopen。
void* dlh = dlopen("./plugin.so", RTLD_NOW);
if (!dlh) { fprintf(stderr, "dlopen failed: %s\n", dlerror());
exit(EXIT_FAILURE); };( dlh通常是一个全局数据)
然后使用dlsym获取函数指针。因此,在程序和插件代码都包含的标题中声明它们的签名,如
typedef int readerfun_t (FILE*);声明一些(经常)全局函数指针
readerfun_t* readplugfun;并在插件句柄dlsym上使用dlh
readplugfun = (readerfun_t*) dlsym(dlh, "plugin_reader");
if (!readplugfun) { fprintf (stderr, "dlsym failed: %s\n", dlerror());
exit(EXIT_FAILURE); };当然,在您的插件源代码中(例如在plugin1.cc中),您将定义
extern "C" int plugin_reader (FILE*inf) { // etc...您可以在插件中定义一些构造函数(或析构函数)(请参见GCC函数属性);应该在dlopen (或dlclose)时调用该函数。在C++中,您应该简单地使用静态对象。(在dlopen时调用它们的构造函数,在dlclose时调用它们的析构函数;因此函数属性的名称)。
在程序调用结束时
dlclose(dlh), dlh = NULL;实际上,您可以执行大量(可能是100万) dlopen调用。
您通常希望将您的主程序与-rdynamic链接,以便从插件中看到它的符号。
gcc -rdynamic prog1.o prog2.o -o yourprog -ldl阅读程序库HowTo & C++ dlopen迷你HowTo & Drepper的论文:
最重要的部分是定义并记录一个插件约定(即“协议”),即插件中所需的一组函数(和API),以及如何使用它们,调用它们的顺序,内存所有权策略等等。如果允许几个类似的插件,您的主程序中可能有一些记录良好的钩子,这些钩子调用相关的dlsym-ed插件的所有dlsym-ed函数。例如:GCC插件惯例,GNU制作模块,Gedit插件 .
https://stackoverflow.com/questions/26669302
复制相似问题