【问题标题】:Dll built in Delphi 2010/2009 not compatible to Delphi 7 when an Exception is raised引发异常时,在 Delphi 2010/2009 中构建的 Dll 与 Delphi 7 不兼容
【发布时间】:2010-06-25 18:38:36
【问题描述】:

我在 Delphi 2010 中构建了一个 dll,它在我的 delphi 7 应用程序中使用。

我知道 unicode AnsiString / string 问题,根据我的测试,一切正常,直到我的 delphi 2010 dll 没有引发异常。

事实是,是否有任何与 unicode/AnsiString 世界兼容的特殊/处理异常?也就是说,我的 Delphi 2010 是否能够引发可以在我的 delphi 7 应用程序中适当处理的异常?

感谢任何帮助。

达尼洛。

【问题讨论】:

  • 异常不应该转义 dll...Dll 可能应该报告错误,然后 D7 应用程序应该检查返回码并在适当的时候引发异常。看看 OLE 的工作原理和 OleCheck 函数。
  • @Marjan:该评论足以成为一个答案。您应该将其作为一个发布并获得一些支持点数。 :)

标签: delphi exception unicode ansistring


【解决方案1】:

看到 Mason 和 Jeroen 都提示我,这里是: (Jeroen,不要放弃你的,你也有有效的积分)。

Jeroen 声明任何特定语言都不应跨越 dll 边界。在某种程度上我同意。这取决于 dll 的预期用途,尤其是涉及到诸如字符串之类的语言特定功能时。如果您开发的 dll 将专门用于 Delphi 项目,尤其是当它仅用于您自己的 Delphi 项目时,没有理由为了避免字符串越界而弄乱 PChar 之类的东西。

因此,即使异常是特定于语言的,对我而言,这并不是不允许异常转义 dll 的主要原因。事实上,由于它们的语言特殊性,不可能在 dll 之外处理它们。

不允许异常逃逸 dll 的基本原因与不允许异常逃逸线程的基本原因相同:清理自己的烂摊子。另外:转义线程的异常会导致您的应用程序崩溃。转义 dll 的异常可能不是这种情况,但 dll - 甚至比线程更应该是一个 自包含 实体,独立于谁调用它,包括独立于调用者处理不可预见的情况,即异常。

那么你如何确保一个 dll 不会践踏调用方?我想通往罗马的道路有很多,但我认为最简单的是 OLE 所做的:

  • 每个导出的方法都应该返回一个代码,告诉调用者是否一切正常,或者是否出现问题。

  • 具体返回代码。不要只报告出了什么问题,要有一个代码来阻止该方法执行它被调用的所有操作。所以有 DLL_OK、DLL_OUT_OF_MEMORY、DLL_FILE_NOT_FOUND、DLL_INVALID_XXX(用于报告无效输入参数)等代码。

  • 在调用 dll 的应用程序中,编写一个通用 DLL_Check 函数来检查返回代码并引发适当的异常,以便其余代码可以根据需要处理。

  • 使用特定的异常类来执行此操作。即一个通用的 EDllError 异常类及其各种后代,用于您需要处理的特定情况。这极大地帮助了除 E... 进行编码。

  • 因为方法的返回值用于ok/error报告:在需要返回有意义值的方法中使用out或var参数。

  • 查看有关 OLE 拖放的 msdn 文档,了解特定返回码的示例以及如何使用 var 和 out 参数与调用者交换信息。

链接:

【讨论】:

    【解决方案2】:

    Delphi 总是“容忍”在调用者和被调用者之间跨越常规 DLL 边界传播的异常。然而,只有当且仅当调用者和被调用者都具有相同的 Delphi 版本时,这种“容忍度”才存在。它在版本之间起作用的事实仅仅是因为对于几个版本,Exception 类的布局和声明没有改变。引入 Delphi 2009 时,许多低级实现细节发生了变化(最明显的是字符串的内部实现)。这就是明显“失败”的原因。异常不应该逃脱 dll 的一条评论非常恰当。

    【讨论】:

      【解决方案3】:

      我会回答的;如果 Marjan 发帖,我会放弃我的。
      编辑:Marjan 要求我保留答案; please reward her answer some up-votes 如果你喜欢我的(因为我的回答深受她的第一条评论的启发)。

      关于 DLL 的整体想法是它们与语言无关。
      异常是高度依赖于语言的特性(许多语言都有它们,但每种语言都以不同的方式实现它们,有时 - 在本例中为 Delphi - 相同语言的不同版本使用不同的方式)。

      所以 DLL 应该只允许与语言无关的功能跨越 DLL 边界。
      与语言相关的功能不应跨越 DLL 边界。
      这包括例外情况。

      这意味着您应该寻找替代方案。
      Windows API 为此使用错误代码 GetLastErrorFormatMessage
      您可以在 DLL 中设计类似的东西。
      请注意,尽管 Delphi 字符串也依赖于语言,因此您应该基于字符数组(或指向字符数组的指针)实现类似 FormatMessage 之类的东西。

      --杰罗恩

      【讨论】:

      • 谢谢,但不要删除您的答案。你也有有效的积分。
      • @Marjan:谢谢。我已对您投了赞成票并编辑了我的答案以直接针对您的答案。应得的信用:-)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-28
      相关资源
      最近更新 更多