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: