什么对C ++插件系统安全?

时间:2008-09-04 08:04:46

标签: c++ api plugins compiler-construction

C ++中的插件系统很难,因为ABI没有正确定义,每个编译器(或其版本)都遵循自己的规则。但是,Windows上的COM表明可以创建一个最小的插件系统,允许具有不同编译器的程序员使用简单的界面为主机应用程序创建插件。

让我们切实可行,在这方面保留C ++标准,除了一分钟之外。如果我想为支持C ++插件的Windows和Mac(以及可选的Linux)编写应用程序,并且我想为插件作者提供相当多的编译器选择(比如不到2年的Visual C ++版本) ,GCC或英特尔的C ++编译器),我可以依靠C ++的哪些功能?

当然,我认为插件是针对特定平台编写的。

在我的脑海中,这里有一些我能想到的C ++功能,我认为是答案:

  • vtable布局,通过抽象类使用对象? (是)
  • 内置类型,指针? (是)
  • 结构,工会? (是)
  • 异常? (无)
  • extern“C”函数? (是)
  • 带有内置参数类型的stdcall非外部“C”函数? (是)
  • 非stdcall非外部“C”函数与用户定义的参数类型? (无)

我很感激您在该领域可以分享的任何经验。如果您知道任何具有C ++插件系统的中等成功的应用程序,那也很酷。

卡尔

8 个答案:

答案 0 :(得分:26)

Dobb博士的日记有一篇文章Building Your Own Plugin Framework: Part 1,这篇文章非常好读。它是一系列文章的开始,涵盖了C / C ++跨平台插件框架的体系结构,开发和部署。

答案 1 :(得分:6)

您可能还想考虑通过脚本界面替换传统的插件界面。对于已经解决了您的问题的C / C ++中的几种脚本语言,有一些非常好的绑定。在它们之上构建可能不是一个坏主意。例如,请查看Boost.Python

答案 2 :(得分:6)

Qt有一个非常好的插件系统,我过去曾经使用过。它使用Qt的元对象系统来克服在尝试开发C ++插件时通常会遇到的许多问题。

一个例子是Q_DECLARE_INTERFACE如何工作,以防止您使用不兼容的插件。另一个是build key,以确保为您的体系结构,操作系统,编译器加载正确的插件。如果您不使用Qt的插件系统,那么您需要担心这些并自行创建解决方案。这不一定是火箭科学,我并不是说你失败了,但奇趣科技的人非常聪明并且花了一段时间思考它,我宁愿使用他们创造的东西而不是自己重新发明轮子

另一个例子是RTTI 通常不能跨DLL边界工作,但是当使用Qt时,依赖于元对象系统的qobject_cast之类的东西可以跨DLL边界工作。

答案 3 :(得分:3)

我认为您可以安全地创建基于以下内容的插件系统:

  • 将插件功能打包到库中(.dll,.so等)
  • 要求插件公开关键的C语言导出。
  • 要求插件实现(并返回指针/引用)抽象C ++接口。

可能是最成功的C ++插件系统:旧的Adobe Photoshop。如果不是这样,其中一种虚拟合成器格式,如VSTi等。

答案 4 :(得分:3)

这本书Imperfect C++ by Matthew Wilson有一个很好的信息。

建议似乎是:只要你使用相同(或equivelant)编译器,你就可以使用C ++,否则你最好在你的C ++代码之上使用C作为接口。

答案 5 :(得分:2)

ACE具有跨平台插件架构。

退房:

  1. ACE DLL
  2. ACE DLL Manager
  3. 我建议查看这本书 The ACE Programmer's Guide

答案 6 :(得分:2)

Firefox在XPCOM(http://www.mozilla.org/projects/xpcom/)上运行。它的灵感来自Microsoft COM,但它是多平台的。

答案 7 :(得分:1)

我有自己的游戏引擎,它有一个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导出和头文件技巧。