经过几个小时的研究,我什么都没有发现,所以我转向你们,希望有一个解决方案的好人。我将用C++编写一个bot,并且在某个时候想为它创建一个插件系统。现在我知道我可以为它编写一种脚本语言,但是,我知道只需编写一个API并在程序运行时将程序链接到该脚本即可。我的问题是,我如何获得动态链接(就像hexchat的插件)?有没有优雅的解决方案,或者至少有关典型设计的理论?编写一个插件系统?
回答
在Linux和POSIX系统,你要使用dlopen(3) & dlsym
(或一些库包装这些功能,例如Glib从GTK,Qt,POCO,等...)。更确切地说,
构建position independent code共享库作为你的插件:
gcc -fPIC -Wall -c plugin1.c -o plugin1.pic.o
gcc -fPIC -Wall -c plugin2.c -o plugin2.pic.o
要注意,如果插件被编码在C++中,你将与g++
编译它,你应该为extern "C"
声明插件的功能,以避免name mangling。
然后链接你的插件作为
gcc -shared -Wall plugin1.pic.o plugin2.pic.o -o plugin.so
您可以(如果你的插件希望GNU的readline上述命令的结束例如-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 function attributes);将在dlopen
(或dlclose
)时间被调用。在C++中,你应该简单地使用静态对象。 (它们的构造函数调用时间为dlopen
,它们的析构函数调用时间为dlclose
;因此函数属性的名称)。
在你的程序调用
dlclose(dlh), dlh = NULL;
年底在实践中,你可以做的dlopen
调用了很多(也许是一百万)。
通常你想你的主程序与-rdynamic
链接让其符号是从插件可见。
gcc -rdynamic prog1.o prog2.o -o yourprog -ldl
阅读Program Library HowTo & C++ dlopen mini HowTo & Drepper's paper: How to Write a Shared Library
最重要的部分是定义和文档插件公约(即, “协议”),即是函数的集合(和API)(以被dlsym
-ed)需要你的插件,以及如何使用它们,其中调用顺序排列,什么是内存的所有权政策,等等。如果你让几个类似的插件,你可能有一些有据可查的钩子钩住你的主要程序,调用所有的dlsym
函数相关的dlopen
-ed插件。示例:GCC plugins conventions,GNU make modules,Gedit plugins,...
- 1. 用C++编写插件系统
- 2. 编写一个系统调用linux
- 3. 编写一个MySQL插件
- 4. 用C++编写的文本编辑器的插件系统
- 5. 建立一个插件系统用PHP
- 6. WinForm插件系统
- 7. MVC3插件系统
- 8. PHP插件系统
- 9. 编写一个Firefox/Netscape插件
- 10. 编写一个简单的仄插件
- 11. 如何编写一个jQuery UI插件?
- 12. 编写一个更好的jQuery插件
- 13. 编写一个新的jQuery插件
- 14. 写入汇编代码系统编程
- 15. 插件系统没有为每个操作系统重建?
- 16. 编写一个简单的工作流程系统
- 17. 如何编写一个系统中使用MySQL和PHP
- 18. 写一个先进的过滤系统
- 19. 获取想写统一的iOS插件
- 20. c#插件系统问题
- 21. Python插件系统 - HOWTO
- 22. C#插件系统设计
- 23. C#某种插件系统
- 24. Phonegap系统通知插件
- 25. C++插件的DLL系统
- 26. 如何在java编程中从系统访问文件到另一个系统?
- 27. 如何编写一个超级简单的软件激活系统?
- 28. 如何用其他语言的绑定编写Qt插件系统?
- 29. 编写访问系统的方法?
- 30. 如何编写网站登录系统
插件系统没有_one_协议。您将需要编写一组类工厂/加载的模块,并在运行时从动态库加载你的代码,根据您的应用程序的需要(我不知道hexchat是什么,以及它如何与插件工作)。实际上,你的问题太宽泛无法回答(但是,请看一下WinAPI LoadLibrary和Linux API dlopen,并考虑围绕这些建立一些东西)。投票结束。 – utnapistim 2014-10-31 08:53:59
由于你标记C:看一看GLibs [GModule](https://developer.gnome.org/glib/stable/glib-Dynamic-Loading-of-Modules.html),然后[GTypeModule](HTTPS:/ /developer.gnome.org/gobject/stable/GTypeModule.html)以获得具有自动界面加载的更复杂版本。 – jku 2014-10-31 09:05:02
我不确定是否理解你的问题。我给了一些答案。 – 2014-10-31 11:14:21