有关实施插件样式系统的哪些提示?
答案 0 :(得分:30)
在C中(我认为C ++也是我自己没有做过),这通常是使用动态加载的模块完成的。这些API依赖于平台。
在POSIX(Linux)上,您使用dlopen()
系列函数。基本上你是单独构建你的插件,然后在运行时加载它,按名称查找它的符号,然后可以调用它们。
对于Win32,LoadLibrary()
执行非常类似的操作,将代码构建到DLL中。
对于使所有这些变得简单透明的方便包装,请查看GLib的GModule API。
答案 1 :(得分:11)
在'92 / '93时间框架中,我研究了Aldus PageMaker的插件架构,该架构采用C ++编码。 PageMaker建立在一个名为VAMP的C ++ OOP框架上,它支持Mac OS和Windows之间的可移植性。
因此我们尝试使用C ++的功能来构建插件架构。由于所谓的脆弱基类问题,这证明对于C ++类来说是非常有问题的。我接着写了一篇发表在期刊上的论文,并在OOPSLA '93的反思研讨会上发表了论文。我还在波特兰的Usenix会议上与Bjarne Stroustrup联系,并与他进行了几个月的对话,在那里他主张代表我处理脆弱的基类问题。 (唉,当时其他问题被认为更重要。)
Microsoft推出了COM / DCOM系统,该平台被视为该问题的可行解决方案。通过用于定义COM接口的抽象类,C ++可以用作COM的实现语言。
然而,现在开发人员避开了COM / DCOM。
相比之下,NeXT在NeXT Step框架中使用Objective C在90年代早期设计了一个插件架构。今天,它在Apple的计算机和iPhone等重要平台上的Mac OS X中充满活力。
我提交的Objective C能够以出色的方式解决插件问题。
我个人认为C ++的脆弱基类问题是最致命的缺陷。
如果使用基于C语言的语言系列构建插件架构,可以使用Objective C来实现。
答案 2 :(得分:11)
我能给出的最好的平台和语言中立的建议是:
围绕插件SDK设计整个应用。
IMO,插件SDK不应该是事后的想法。如果您将应用程序设计为基本上是一个加载插件的空壳,那么核心功能将在您自己的SDK中实现,您将获得以下好处:
在C / C ++中,您可能使用动态链接库以及函数指针(C)或接口(仅由纯虚方法组成的类,用于C ++)。但即使您使用Javascript,我仍然会推荐上述架构。
答案 3 :(得分:5)
这可能不是您正在寻找的,但您可以在您的应用程序中嵌入脚本语言,例如Lua。 Lua旨在嵌入其他程序中,并用作编写插件的脚本语言。我相信将Lua解释器添加到您的程序中相当容易,但我不知道Lua所以我无法保证解决方案的效果如何。其他对Lua有更多经验的人,请添加关于将Lua嵌入另一个应用程序的经验的评论。
这当然意味着你的插件需要用Lua编写。如果您不喜欢Lua,那么 de-facto 标准Perl,Python和Ruby解释器都是用C语言编写的,并且可以嵌入到C程序中。我知道有很多程序使用这些语言作为脚本语言扩展。
然而,我不知道你在寻找什么,因为你的问题有点模糊。也许有关您希望人们能够使用所述插件做什么的更多信息是合适的。对于某些任务,完整的脚本语言可能有点矫枉过正。
答案 4 :(得分:5)
Qt提供QPluginLoader: http://qt-project.org/doc/qt-4.8/qpluginloader.html
如果您需要/想要更精细的控制,Qt还提供了一种使用QLibrary动态加载库的方法: http://qt-project.org/doc/qt-4.8/qlibrary.html
更好的是,它们可以跨平台移植。
答案 5 :(得分:3)
最好使用像ACE(http://www.cs.wustl.edu/~schmidt/ACE.html)这样的框架来保护您(尽可能好)平台特定的编码。
ACE包含一个基于共享库的插件框架,您可以使用它来创建动态组合的应用程序。
对于更高级别的抽象,请查看CIAO(http://www.cs.wustl.edu/~schmidt/CIAO.html)CORBA组件模型的开源C ++实现。
答案 6 :(得分:2)
看看Poco Class Loader,这对你来说很有意思。
答案 7 :(得分:2)
我写了一篇关于如何使用动态链接库实现插件系统的文章。本文是从Windows程序员的角度编写的,但该技术可以应用于Linux / Unix类型的环境。
可在此处找到该文章:http://3dgep.com/?p=1759
重点是,您应该创建一个“公共”DLL,它由主应用程序(核心应用程序)和插件实现隐式链接。然后,核心应用程序可以在运行时动态显式链接和加载插件。
本文还介绍了如何使用“公共”DLL安全地跨多个DLL共享类的静态(单例)实例。
本文还介绍了如何从DLL导出“C”函数或变量,并在运行时使用应用程序中的导出函数。
答案 8 :(得分:1)
答案 9 :(得分:0)
我使用一个相当天真的系统取得了一些成功:
答案 10 :(得分:0)
我编写了一个插件库Pugg,它从dll文件中加载C ++类,这是我使用的逻辑:
用户从具有唯一名称的dll导出c函数。此名称必须足够独特,因为从dll加载时无法使用参数区分函数。
C函数注册一个或多个名为“Driver”的工厂类。每个Driver类都与一个字符串相关联。当主应用程序想要创建一个类时,它使用关联的字符串收集相关的工厂类。我还实现了一个版本检查系统,不加载旧的插件。
使用LoadLibraryA和GetProcAddress函数完成Dll加载(Pugg目前适用于Windows)。
值得一提的是,应该使用相同的编译器并使用相同的编译选项(发布/调试模式,优化设置,stl版本等)编译主应用程序和dll。否则可能会出现类映射问题。