用C或C ++实现插件系统

时间:2009-04-02 06:34:04

标签: c++ c plugins

有关实施插件样式系统的哪些提示?

11 个答案:

答案 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中实现,您将获得以下好处:

  • 组件的高度模块化,以及明确的目的分离(这有助于您的架构变得更好)
  • 它强制您的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)

我使用一个相当天真的系统取得了一些成功:

  • 为插件创建API规范
  • 使用单例插件管理器
  • 使用基于LoadLibrary / GetProcAddress的运行时动态链接
  • 实现基于控件的事件处理反转以通知插件

答案 10 :(得分:0)

我编写了一个插件库Pugg,它从dll文件中加载C ++类,这是我使用的逻辑:

用户从具有唯一名称的dll导出c函数。此名称必须足够独特,因为从dll加载时无法使用参数区分函数。

C函数注册一个或多个名为“Driver”的工厂类。每个Driver类都与一个字符串相关联。当主应用程序想要创建一个类时,它使用关联的字符串收集相关的工厂类。我还实现了一个版本检查系统,不加载旧的插件。

使用LoadLibraryA和GetProcAddress函数完成Dll加载(Pugg目前适用于Windows)。

值得一提的是,应该使用相同的编译器并使用相同的编译选项(发布/调试模式,优化设置,stl版本等)编译主应用程序和dll。否则可能会出现类映射问题。