对于C ++插件系统,什么是安全的?
由于未正确定义ABI,并且每个编译器(或者其版本)遵循其自己的规则,因此C ++中的插件系统很难。但是,Windows上的COM显示可以创建一个最小的插件系统,该系统允许具有不同编译器的程序员使用简单的界面为主机应用程序创建插件。
让我们切合实际,将C ++标准留出一分钟的时间,这对这方面不是很有帮助。如果我想为Windows和Mac(以及可选的Linux)编写一个支持C ++插件的应用程序,并且如果我想为插件作者提供相当多的编译器选择(例如,不到2年的Visual C ++版本) ,GCC或者Intel的C ++编译器),我可以依靠C ++的哪些功能?
当然,我假设插件将针对特定平台编写。
在我脑海中,下面是一些我能想到的C ++功能,我认为是答案:
- vtable布局,以通过抽象类使用对象? (是的)
- 内置类型,指针? (是的)
- 结构,工会? (是的)
- 例外? (不)
- 外部" C"功能? (是的)
- 带有内置参数类型的stdcall非外部" C"函数吗? (是的)
- 具有用户定义参数类型的非stdcall非外部" C"函数? (不)
我们在此领域可以分享的任何经验,我将不胜感激。如果我们知道具有C ++插件系统的任何中度成功的应用程序,那也很酷。
卡尔
解决方案
回答
Dobb博士在Journal上发表了一篇文章,《构建自己的插件框架:第1部分》,这是关于该主题的不错的阅读。这是一系列文章的开头,涵盖了C / C ++跨平台插件框架的体系结构,开发和部署。
回答
我有一个带有C ++插件系统的游戏引擎。
我在头文件中有一些代码,因此将其放入插件的编译单元中。
主机中较大的函数通过导出的C函数调用(插件调用MyObject_somefunction(MyObject * obj),而在引擎中仅调用obj-> somefunction())。如果我们觉得C函数的调用很丑陋,那么在将头文件包含在插件中的情况下,可能会有一些头技巧,请使用#defined成员函数来调用C函数:
#if defined(IN_THE_PLUGIN) void MyObject::somefunction() { MyObject_somefunction(this); } #endif
虚函数必须是纯函数,或者代码位于头文件中。如果我不是从类继承而只是实例化一个,则虚拟函数代码可以存在于引擎中,但是该类必须导出一些C函数以创建和销毁从插件调用的对象。
基本上,我使用过的技巧(旨在保持平台的整体独立性)仅相当于C导出和头文件技巧。
回答
我们可能还需要考虑用脚本接口替换传统的插件接口。对于C / C ++中的几种脚本语言,有一些非常好的绑定已经解决了问题。在它们之上进行构建可能不是一个坏主意。例如,看一下Boost.Python。
回答
我认为我们可以安全地创建基于以下内容的插件系统:
- 将插件功能打包到库中(.dll,.so等)
- 要求插件公开关键的C语言导出。
- 要求插件实现(并返回一个指针/引用)抽象的C ++接口。
可能是最成功的C ++插件系统:老式的Adobe Photoshop。如果不是那样,则是虚拟合成格式之一,例如VSTi等。
回答
马修·威尔逊(Matthew Wilson)撰写的《 Imperfect C ++》一书对此提供了很好的信息。
似乎建议是:只要使用相同(或者等效)编译器,就可以使用C ++,否则最好将C用作C ++代码之上的接口。
回答
Qt对于我过去使用的插件有一个非常好的系统。它使用Qt的元对象系统来克服尝试开发C ++插件时通常会发现的许多问题。
一个示例是Q_DECLARE_INTERFACE
的工作方式,以防止我们使用不兼容的插件。另一个是构建密钥,以确保为体系结构,操作系统,编译器加载正确的插件。如果我们不使用Qt的插件系统,那么我们将不得不担心这些事情,并自行发明解决方案。不一定是火箭科学,我并不是说我们会失败,但是Trolltech的家伙很聪明,花了一段时间思考,我宁愿使用他们创造的东西,也不愿自己重新发明轮子。 。
另一个例子是RTTI通常不能跨DLL边界工作,但是当使用Qt时,依赖于元对象系统的qobject_cast之类的东西确实可以跨DLL边界工作。
回答
ACE具有跨平台插件体系结构。
退房:
- ACE DLL
- ACE DLL管理器
我建议检查一下这本书
ACE程序员指南
回答
Firefox在XPCOM(http://www.mozilla.org/projects/xpcom/)上运行。它受到Microsoft COM的启发,但是它是多平台的。