使用Delphi创建的DLL在其他Delphi版本中运行良好,应该遵循哪些原则?
Posted
技术标签:
【中文标题】使用Delphi创建的DLL在其他Delphi版本中运行良好,应该遵循哪些原则?【英文标题】:What principles should be followed to make a DLL created using Delphi works well in other Delphi version? 【发布时间】:2009-11-17 02:04:47 【问题描述】:在this question 之后,我需要知道应该遵循哪些原则才能将一个类封装到一个与其他版本的Delphi 兼容的dll 中。 我使用 RAD2010 中的泛型功能创建了一个类,并创建了一个 dll,该 dll 具有返回它的实例的函数。当我尝试使用 BDS2006 或 Delphi 6 使用 dll 时,DLL 没有按预期工作。但是如果我在其他电脑上使用RAD2010,就没有问题。是不是因为使用了以前 Delphi 版本中没有的功能(堆栈东西?)? 对于字符串问题,我已经遵循库文件中的注释指南,即我将 ShareMem 放入库首先使用子句和我的项目中。我已将 borlndmm.dll 从 RAD2010 复制到我使用 BDS2006 尝试 DLL 的同一文件夹中。它没有崩溃,但没有达到预期的效果。一个函数在 RAD2010 环境中运行良好时返回一个空字符串。
再一次,我有一个问题:应该遵循哪些原则才能使 dll 中的类封装与其他版本的 Delphi 兼容?先感谢您。 (在不使用OOP时将函数封装在dll中,其他版本的Delphi我没有发布)。
【问题讨论】:
【参考方案1】:字符串的定义随着 D2009 的变化而改变。如果您想让字符串通信安全,请使用 PAnsiChar 或 WideString。
通过 DLL 进行通信的基本规则是不使用任何特定于 Delphi 的东西,因此不使用 Delphi 字符串,也不使用 TObject 后代。不过,接口、记录和 COM 类型工作正常。
【讨论】:
我想强调第二段。如果您没有看到 Windows API 中公开的功能,也不要在您自己的 DLL 中公开它。假设您正在编写一个供 C 使用的 DLL,甚至供您从未见过的某些环境使用。 +1。值得指出的是,接口方法参数和函数结果中不应该(必须)没有任何 Delphi 特定类型,也不应该作为这些记录的一部分。 +1。可能不相关,但如果您打算在 Delphi 以外的语言中使用它们,请不要忘记将所有(非 COM)DLL 导出声明为 stdcall。 我是这么认为的。我认为 DLL 可能是 Windows 环境中的灵丹妙药。 BPL 仅适用于相同的 Delphi 版本。好的,就我而言,唯一的目的是在我修补课程时放松。不分享给其他版本的Delphi。谢谢你们。好的,我试试用PAnsiChar或者低版本做DLL,然后在RAD2010上试试。【参考方案2】:你问:
再一次,我有一个问题:应该遵循哪些原则才能使 dll 中的类封装与其他版本的 Delphi 兼容?
只有一个:不要这样做。你做不到。要么您编写一个 DLL,然后使用可以在 DLL 中安全使用的惯用语和数据类型,这会排除(除其他外)类。
或者你编写一个 BPL,然后你可以安全地导出类,使用字符串等等,但是你被绑定到同一个 Delphi 版本。此限制具有技术性质,因此编写 DLL 将不会解决它。可能有一些技巧可以克服这个问题,并且可能有不同的 Delphi 版本使用相同的类布局以便它工作,但你不能将你的公共 DLL 接口绑定到这些实现细节。
【讨论】:
【参考方案3】:只使用基本类型。如果您使用接口,请使用类型库编辑器创建它们,以便一开始就受兼容类型的约束。一个好的经验法则是查看 Windows API 并尝试模拟其调用约定。
你可以在你的 DLL 中使用类,但你不能像这样公开它们。一个适用于 DLL 的好习惯是句柄概念。您的 DLL 创建一个对象并返回该对象的句柄。当您需要再次使用该对象时,您可以向 DLL 中的函数传递一个句柄。请记住,您的 DLL 需要完全负责对象的内存和生命周期。创建 DLL 函数以公开您也需要访问的类的片段是一个简单的过程。
在 Delphi 方面,您可以编写一个代理包装器,对用户隐藏句柄。对于事件,您可以使用回调方法。基本上,您将非对象函数指针传递给 dll,然后它在事件上调用该函数。 Delphi 3000 上提供了此过程的快速概述。
【讨论】:
以上是关于使用Delphi创建的DLL在其他Delphi版本中运行良好,应该遵循哪些原则?的主要内容,如果未能解决你的问题,请参考以下文章