我正在寻找添加的能力,为用户写插件的程序,我已经在 Delphi 开发。该程序是一个单一的可执行文件,没有使用DLL。
这将允许用户社区为我的程序编写扩展,以访问内部数据并添加他们可能发现有用的功能。
我在以下位置看到了该帖子:Suggestions for Adding Plugin Capability?,但它的答案似乎不能转移到 Delphi 程序。
如果可能的话,我希望添加此功能,并将我的应用程序保持为单个可执行文件,而不需要任何DLL或其他模块。
您是否知道有任何资源、组件或文章可以建议如何在 Delphi 中最好地做到这一点,或者您有自己的建议吗?
9条答案
按热度按时间3mpgtkmj1#
我想问的第一个问题是,您是否需要插件来访问宿主应用程序的UI,或者添加自己的UI元素?或者插件是否仅限于查询和/或向宿主应用程序提供数据?
后者要简单得多,并提供了两种可能性。其他人已经提到了DLL,这是第一种方法。某些警告适用--一般来说,你应该只使用Windows API中使用的数据类型与DLL接口。这样你就可以确保插件DLL将理解你的数据类型,无论它们是用什么语言/编译器创建的。(例如,使用PCars,而不是字符串。通常不要将 Delphi 类(如TStream)传递给DLL。这在某些情况下似乎可以工作,但通常是不安全的,因为即使DLL是在Delphi中编译的,它也可能是不同版本的编译器,在 Delphi 中使用DLL,你会发现更多的技巧。
另一个尚未提及的方法是在您的应用程序中启用脚本。有几个非常强大的第三方脚本引擎,既有商业的也有免费的,它们中的大多数允许您用脚本交换 Delphi 对象。其中一些库只支持Pascal作为脚本语言,其他的会让你使用Basic(也许对初学者更好)或其他语言。例如,请参见http://www.remobjects.com/free.aspx上的RemObjects Pascal脚本(免费)。
目前我最喜欢的脚本解决方案是Python for Delphi (P4 D,也是免费的)from http://mmm-experts.com/Products.aspx?ProductID=3它可以通过RTTI与你的类漂亮地接口,并允许你在你的 Delphi 应用程序中执行Python代码,以及在Python脚本中使用Delphi类。考虑到Python的流行,如果你想吸引开发者到你的项目中来,这可能是一个可行的解决方案。然而,每个用户都需要安装Python发行版。
在我看来,从潜在的插件作者的Angular 来看,使用脚本比选择DLL的门槛要低。
现在,回到我最初的问题:如果你需要插件与你的用户界面进行交互,比如在上面放置控件,那么事情就变得更加复杂了。通常,DLL不能用来做这件事。Borland/CodeGear认可的方法是使用包(BPLs)。使用BPLs,你可以访问和示例化插件提供的类,就像它们在你的宿主应用程序中被声明一样。捕获是,所有的BPL都必须使用与你的主应用程序完全相同的 Delphi 版本和内部版本来编译。在我看来,这使得包完全不切实际,因为很难期望世界上所有潜在的插件编写者都使用与你相同的Delphi版本。这是一个主要的陷阱。
为了解决这个问题,我尝试了一种不同的方法:继续使用DLL,为插件开发语法来描述它所需要的UI,然后在宿主应用程序中自己创建UI。(XML是一种表达UI的方便方式,因为您可以免费获得父代/嵌套的概念。)UI描述语法可以包含对DLL的回调,当控件的内容或状态更改时触发该回调。这个方法将插件限制在你的应用程序已经使用或注册的VCL控件集内。
谷歌搜索“ Delphi plugin framework”,也有一些现成的解决方案,但据我所知,他们通常使用BPL,其实用性有限。
6fe3ivhb2#
实际上,您所引用的问题的公认答案也非常适合 Delphi 。您的插件将是DLL,您可以指定它们应该导出一个具有特定名称和签名的函数。然后,您的程序将加载DLL(使用
LoadLibrary
)并取得函式的位址(使用GetProcAddress
)。如果DLL未载入,或函式不存在,则DLL不是应用程序的插件。获得DLL的地址后,就可以调用它了。可以将一个接口传递给函数,该接口表示您希望公开的应用程序部分。还可以要求函数返回一个接口,其中包含应用程序将在不同时间调用的方法。
在测试插件系统时,最好用 Delphi 以外的语言自己编写一个插件。这样,您就可以更加确信您没有无意中要求每个人都使用Delphi。
qmb5sa223#
一开始我选择了BPL和DLL基础插件,发现它们很难维护。
如果你使用BPL系统,那么你需要匹配BPL版本与EXE版本。这包括 Delphi 更新,这可能会打破一些东西。我发现(艰难的方式),如果我需要包括我所有的插件与每个版本,有插件没有意义。
然后我切换到普通的DLL插件。但那个系统只是复杂的代码库。这不是一件好事。
在上网的时候,我发现了Lua嵌入式脚本语言,并与它一起交付。Lua是150K的DLL,嵌入了字节码编译器,解释器和非常简单和聪明的动态编程语言。
我的插件是简单的Lua脚本。很容易维护和制作。有预先制作的 Delphi 例子,所以你可以导出任何类或过程作为Lua表或函数。GUI或没有。例如,我在我的应用程序中有TurboPower Abbrevia用于压缩。我导出了我的压缩类到Lua,现在所有的插件都可以调用zip('*. ',' dir.zip')和unzip()。然后我切换到7zip,只实现了旧的类来使用7zip。所有插件都像它们一样工作,支持新的zip('. *',' dir.7z')。
我制作了TLuaAction,它从脚本中调用Execute()、Update()、Hint()过程。
Lua也有它自己的插件系统,使它很容易添加功能。例如,luacom make很容易使用COM自动化,luainterface允许从Lua调用.net。更多信息请参见luaforge。有用 Delphi 制作的Lua IDE,带有源代码。
qlfbtfca4#
不久前,我试着对所有这些选项做了一个概述。我们和我的读者/评论者一起建立了这个列表:
1u4esq0p5#
添加插件功能最通用的方法是使用COM。Eric Harmon的Delphi Com Programming是一本让您开始使用的好书。虽然它最初是为 Delphi 版本3到5编写的,但书中的内容在Delphi的最新版本中仍然有效。
就我个人而言,我已经将此技术与活动脚本沿着使用,以允许最终用户进行自定义。
idv4meu86#
我正在使用插件来实现我正在构建的游戏引擎中的大多数功能。主EXE由一个脚本引擎、一个插件管理器、一些基本的图形例程组成,除此之外没有其他内容。我正在使用JEDI VCL库中的TJvPluginManager。它是一个非常好的管理器,并且它可以添加任何你想要的东西到你的程序中。查看这个包中包含的演示来了解它是如何工作的。唯一的缺点是它添加了很多JCL/JVCL代码添加到您的程序中,但是如果您已经在使用其他JVCL组件,这就不是问题了。
weylhg0b7#
如果插件是在 Delphi 或C++ Builder中开发的,使用包+接口。Delphi OTA是一个很好的例子。如果插件是独立于语言的,COM是一个很好的选择。
补充:如果你不使用COM,你可能需要为每一种语言提供SDK。不同语言之间的数据类型处理可能是痛苦的(例如 Delphi 字符串类型)。Delphi COM支持是优秀的,你不需要担心的细节。这些大多是隐含的Delphi COM支持。不要试图发明轮子了。我很惊讶为什么人们不倾向于提到它。
w80xi6nr8#
我找到了Tim Sullivan的一篇文章:
Implementing Plug-Ins for Your Delphi Applications
7ajki6be9#
你可以看看Remobjects的Hydra,它不仅允许你添加插件,还可以混合win32和. net。