views:

95

answers:

3

Hello guys,

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.

+2  A: 

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

Jeroen Pluimers
Thanks, but don't delete your answer. You have valid points as well.
Marjan Venema
@Marjan: Thx. I've upvoted you and edited my answer to direct to yours. Credit where it is due :-)
Jeroen Pluimers
+2  A: 

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.

Allen Bauer
+3  A: 

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:

Marjan Venema