当引发异常时,Delphi 2010/2009 中构建的 Dll 与 Delphi 7 不兼容
我在 Delphi 2010 中构建了一个 dll,并在我的 Delphi 7 应用程序中使用它。
我知道 unicode AnsiString / string 问题,根据我的测试,到目前为止一切都工作正常,我的 delphi 2010 dll 没有引发任何异常。
事实是,是否有任何特殊/处理的异常与 unicode/AnsiString 世界兼容?也就是说,我的 Delphi 2010 是否能够引发可以在我的 Delphi 7 应用程序中适当处理的异常?
感谢您的帮助。
达尼洛.
I've built a dll in Delphi 2010 and it's consumed in my delphi 7 application.
I'm aware of the unicode AnsiString / string matter and according to my tests everything works fine up to the moment that no exception is raised by my delphi 2010 dll.
The fact is, is there any special/treated exception that is compatible to the unicode/AnsiString world? That is, is my Delphi 2010 able to raise an exception that can be handled appropriately in my delphi 7 app?
thanx for any help.
Danilo.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
鉴于梅森和杰罗恩都提示我,这里是:
(杰罗恩,不要放弃你的,你也有有效的积分)。
Jeroen 指出,任何特定于语言的内容都不应跨越 dll 边界。在某种程度上我同意。这取决于 dll 的预期用途,特别是当涉及到诸如字符串之类的语言特定功能时。如果您开发一个专门用于 Delphi 项目的 dll,特别是仅用于您自己的 Delphi 项目时,则没有理由仅仅为了避免字符串越界而搞乱 PChar 等。
因此,即使异常是特定于语言的,对我来说,这并不是不允许异常逃逸 dll 的主要原因。事实上,由于它们的语言特殊性,不可能在 dll 之外处理它们。
不允许异常逃逸 dll 的基本原因与不允许异常逃逸线程的基本原因相同:清理自己的混乱。另外:逃逸线程的异常将使您的应用程序崩溃。对于转义 dll 的异常来说,情况可能并非如此,但 dll - 甚至比线程更应该是一个自包含实体,独立于谁调用它,包括独立于调用者处理不可预见的情况,即异常。
那么如何保证一个dll不会践踏调用者一方呢?我想条条大路通罗马,但在我看来最简单的是 OLE 所做的:
每个导出的方法都应该返回一个代码,告诉调用者是否一切正常,或者是否出了问题。
返回代码要具体。不要只是报告出现的问题,要为阻止该方法执行其调用的操作的所有内容编写代码。因此,有 DLL_OK、DLL_OUT_OF_MEMORY、DLL_FILE_NOT_FOUND、DLL_INVALID_XXX(用于报告无效输入参数)等代码。
使用特定的异常类来执行此操作。即一般的 EDllError 异常类及其各种后代,用于您需要处理的特定情况。这对 E...do 编码有很大帮助。
因为方法的返回值用于ok/error报告:在需要返回有意义值的方法中使用out或var参数。
查看有关 OLE 拖放的 msdn 文档,了解特定返回代码的示例,以及如何使用 var 和 out 参数与调用者交换信息。
查看有关
链接:
数据传输入口点:http: //msdn.microsoft.com/en-us/library/ms680067(v=VS.85).aspx
DoDragDrop 函数:http ://msdn.microsoft.com/en-us/library/ms678486(v=VS.85).aspx
Seeing as both Mason and Jeroen prompted me, here goes:
(Jeroen, don't drop yours, you have valid points as well).
Jeroen states that nothing language specific should cross a dll boundary. Up to a point I agree. It depends on the intended use of the dll, especially when it comes to such language specific features as string. If you develop a dll that is going to be used exclusively with Delphi projects, and especially when that is only with your own Delphi projects, there is no reason to mess with PChar's and the like just to avoid strings crossing the boundary.
So even though exceptions are language specific, to me that is not the main reason for not allowing exceptions to escape the dll. Nor the fact that because of their language specificity it could be impossible to handle them outside of the dll.
The basic reasons for not allowing exceptions to escape a dll are the same as for not allowing exceptions to escape a thread: clean up your own mess. Plus: an exception escaping a thread will bring your app come crashing down. That may not be the case for an exception escaping a dll, but a dll - even more than a thread should be a self-contained entity, independent of who is calling it and that includes being independent of the caller in handling unforeseen circumstances, ie exceptions.
So how do you ensure that a dll does not trample all over the caller's party? I guess there are many roads that lead to Rome, but the simplest to my mind is what OLE does:
Every exported method should return a code which tells the caller if everything was fine, or if something went wrong.
Be specific in return codes. Don't just report something went wrong, have a code for everything that stops the method from doing what it was called to do. So have codes like DLL_OK, DLL_OUT_OF_MEMORY, DLL_FILE_NOT_FOUND, DLL_INVALID_XXX (for reporting invalid input parameters), etc.
In the app calling the dll, code a general DLL_Check function to check the return codes and raise appropriate exceptions that the rest of your code can handle as it sees fit.
Use specific exception classes to do this. Ie a general EDllError exception class and various descendants thereof for specific situations you need to handle. This aids greatly in the except on E... do coding.
Because the return value of a method is used for ok/error reporting: use out or var parameters in methods that need to return meaningful values.
Check the msdn documentation on OLE drag drop for examples of specific return codes and how to use var and out parameters to exchange information with the caller.
Links:
Data transfer entry point: http://msdn.microsoft.com/en-us/library/ms680067(v=VS.85).aspx
DoDragDrop function: http://msdn.microsoft.com/en-us/library/ms678486(v=VS.85).aspx
Delphi 始终“容忍”跨常规 DLL 边界在调用者和被调用者之间传播的异常。然而,只有当且仅当调用者和被调用者都具有相同的 Delphi 版本时,这种“容忍”才是存在的。它在版本之间工作的事实仅仅是因为对于几个版本来说,Exception 类的布局和声明没有改变。当 Delphi 2009 推出时,许多低级实现细节发生了变化(最显着的是字符串的内部实现)。这就是明显“失败”的原因。异常不应该逃逸 dll 的一个评论是非常恰当的。
Delphi has always "tolerated" exceptions propagating between the caller and the callee across a regular DLL boundary. However that "tolerance" has only been if and only if both the caller and callee are of the same Delphi version. The fact that it worked between versions was merely because for several releases the layout and declaration of the Exception class hasn't changed. When Delphi 2009 was introduced, a lot of low-level implementation details changed (most notably the the internal implementation of strings). This is the cause of the apparent "failure." The one comment that exceptions should never escape a dll is very apropos.
我会给出答案;如果 Marjan 发帖,我就会放弃我的帖子。编辑:Marjan 要求我保留我的答案; 如果您喜欢我的答案,请奖励她的回答一些赞成票(因为我的回答受到了她的第一条评论的极大启发)。
关于 DLL 的整体思想是它们是独立于语言的。
异常是一个高度依赖于语言的功能(许多语言都有它们,但每种语言都以不同的方式实现它们,有时 - 在这种情况下是 Delphi - 相同语言的不同版本使用不同的方式)。
因此 DLL 应该只让与语言无关的功能跨越 DLL 边界。
语言相关功能不应跨越 DLL 边界。
这包括例外情况。
这意味着您应该寻找替代方案。
Windows API 使用错误代码 GetLastError 和 FormatMessage 为此。
您可以在 DLL 中设计类似的东西。
请注意,Delphi 字符串也与语言相关,因此您应该基于字符数组(或指向字符数组的指针)实现类似 FormatMessage 的内容。
——杰罗恩
I'll kick in the answer; if Marjan posts, I'll drop mine.Edit: Marjan has asked me to keep my answer; please reward her answer some up-votes if you like mine (as my answer was greatly inspired by her first comment).
The whole idea about DLL's is that they are language independent.
Exceptions are a highly language dependent feature (many languages have them, but each implements them in a different way, sometimes - in this case Delphi - different versions of the same languages use a different way).
So DLL's should only let language independent features cross the DLL boundaries.
Language dependent features should not cross DLL boundaries.
This includes exceptions.
Which means you should look for an alternative.
The Windows API uses error codes, GetLastError and FormatMessage for this.
You could devise something similar in your DLL.
Be aware though that Delphi strings are language dependent too, so you should implement something like FormatMessage based on character arrays (or pointers to character arrays).
--jeroen