如何从可执行文件中调用位于 bpl 中的 Delphi 函数?

8

我有一个使用Delphi编写的应用程序,为其编写了一个相当简单的包装器.exe。

基本上,有一个dll文件其中包含一堆函数,其中一个函数在我的包装器完成所需操作后会被迭代地调用。我无法控制这个DLL文件,并且永远不会有此权限。

现在,这个DLL已经成为了一个BPL文件,我不确定如何调用其中的函数。提前感谢。

3个回答

10
使用一个包中的函数的简单方法是“使用”包含该函数的单元,像平常一样调用它,并将该包添加到项目的运行时包列表中。为了使其工作,有几个要求:
  1. 您的项目必须使用与编译包时相同的Delphi版本。
  2. 您必须能够访问该单元的DCU文件,或者至少访问该包的DCP文件。
  3. 当程序启动时,该包必须存在于操作系统的搜索路径中。
如果无法满足第三个要求,或者不想始终加载该包,则可以改为调用LoadPackage。使其工作的方法是拥有另一个始终被加载的包。它将被您的项目和您希望加载的包同时使用。中间包将公开一个接口(例如一些注册函数、变量或类),主包可以使用该接口告诉应用程序其功能是什么。您将无法直接在应用程序中“使用”主包的单元。
如果无法满足前两个要求,则有更困难的方法,这也是您需要做的,如果您的应用程序不是用Delphi或C++ Builder编写的。将包视为普通的DLL。使用LoadLibrary加载它。使用GetProcAddress加载其Initialize函数,然后调用它。(请记住,调用约定是register,而不是stdcall。)然后加载您想要调用的函数的地址,注意函数名称已被编码以包括一些单元和类型信息。在调用FreeLibrary之前调用Finalize函数。检查LoadPackageUnloadPackage的源代码;是否需要调用CheckForDuplicateUnits可能取决于您是否能够满足第1个要求。

你能指引我一个做这个的资源吗?实际上我不是 Delphi 程序员,所以对于其中一些东西感到困惑。 - Dan
我不知道是否有任何资源描述如何按照我在最后一段中概述的方式“手动”加载包。使用包的正常方式,如倒数第二段所述,是我期望出现在Delphi帮助文件中的内容,尽管我无法自行检查,因为我没有在任何地方安装Delphi。 - Rob Kennedy

2

BPL(包装式库)只是在DLL基础上增加了一些特定的功能。您应该可以像使用DLL一样轻松调用其中的函数,但有一个特殊的注意事项:BPL必须使用与您所使用的Delphi版本相同的版本进行构建。如果您没有源代码,则这可能是一个主要的缺点。如果这对您造成了问题,您应该与创建者联系并请求将其转换回DLL。


-1,我强烈反对“回到DLL-Hell”的想法。BPL提供了非常丰富的接口和透明的内存管理。 - H H
如果坚持使用DLL接口和兼容DLL的类型(首先不使用字符串),那么可以使用不同版本的Delphi构建BPL。 - mghie
Henk:是的,这正是我所说的。问题在于使用第三方提供的BPL将使您与该版本绑定在一起,除非他们也这样做,否则无法升级或降级。这就是为什么没有经验的Delphi开发人员使用仅限二进制组件包的原因。 - Mason Wheeler
2
Henk,仅使用DLL不会产生“DLL地狱”。如果是这样的话,那么BPL也没有任何区别,因为它们也是DLL。使用包也不能解决在DLL地狱中出现的任何问题。DLL地狱是在单个安装位置管理DLL的冲突版本的问题。您同样可以拥有BPL的冲突版本。 - Rob Kennedy
Rob,你对于DLL-Hell的一般含义是正确的,我使用这个术语是考虑到传输一个简单字符串或记录数组所需的工作量。而BPL确实解决了大部分DLL问题。 - H H
显示剩余3条评论

1
一个BPL可以消除很多DLL问题。如果你可以静态链接它,边界几乎变得透明。如果你必须动态加载它,你需要一个类似DLL的访问函数(通常返回一个对象或接口)和一些公共类型(接口)定义。所有这些都应该由BPL的制造商提供。

将“具有一堆函数的dll,其中一个我会调用”制作成BPL的好处是什么?您列举的所有好处似乎都与OP无关。也许他也没有遇到那些DLL问题? - mghie
取决于该函数的参数。也许丹可以发布一个标题行。 - H H

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接