2

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

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

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

感谢任何帮助。

达尼洛。

4

3 回答 3

4

看到梅森和杰罗恩都提示我,这里是:(杰罗恩,不要放弃你的,你也有有效的积分)。

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 参数与调用者交换信息。

链接:

于 2010-06-26T08:10:04.230 回答
3

我会回答的;如果 Marjan 发帖,我会放弃我的。
编辑:Marjan 要求我保留我的答案;如果你喜欢我的,请奖励她的回答(因为我的回答受到了她的第一条评论的极大启发)。

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

所以 DLL 应该只让与语言无关的特性跨越 DLL 边界。
与语言相关的功能不应跨越 DLL 边界。
这包括例外。

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

——杰伦

于 2010-06-25T22:05:55.223 回答
3

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

于 2010-06-25T22:09:38.573 回答