www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Workaround to "import" an exception from a DLL

reply frame <frame86 live.com> writes:
I know I cannot throw exceptions from a DLL, it will crash. So I 
currently use a wrapper that collects exceptions and pick it up 
if the wrapper method returns a failure state.

As I know what type of exception will be thrown, I can copy all 
important data to a new exception object and then throwing it in 
the current context.

However, I wonder if there is way to copy the exception data via 
Throwable interface direct because checking for types via 
typeid() and string comparsion is just meh.

It is possible to fetch the exception data:

// Throwable e;

// this returns null in the program (but works in a debugger 
watch):
MyExceptionObj imported = cast(MyExceptionObj)e;

// this actually works:
MyExceptionObj imported = cast(MyExceptionObj) cast(void*)e;

But for some reason throwing this object directly would crash.

Is there are way to copy the exception data in a new Throwable 
instance that can be thrown from the current context? Or can the 
runtime be tricked by overwriting the TypeInfo in memory? (I 
don't know exactly what the actual problem is.)
Mar 14 2021
next sibling parent reply evilrat <evilrat666 gmail.com> writes:
On Sunday, 14 March 2021 at 09:35:40 UTC, frame wrote:
 // this returns null in the program (but works in a debugger 
 watch):
 MyExceptionObj imported = cast(MyExceptionObj)e;

 // this actually works:
 MyExceptionObj imported = cast(MyExceptionObj) cast(void*)e;
 Is there are way to copy the exception data in a new Throwable 
 instance that can be thrown from the current context? Or can 
 the runtime be tricked by overwriting the TypeInfo in memory? 
 (I don't know exactly what the actual problem is.)
As a workaround maybe you could introduce special DLLWrapperException with reference to original exception using cast hack? The problem is that TypeInfo is not shared on Windows, which is actually roots deeper in the other problems with "sharing". Unfortunately I cannot provide you with details, but this situation is well known long standing issue. From what I understand it is such a mess because D compiler/linker doesn't merge multiple symbols in running program which is how it basically works in C++ where DLL's works "as expected".
Mar 14 2021
next sibling parent Adam D. Ruppe <destructionator gmail.com> writes:
On Sunday, 14 March 2021 at 12:27:17 UTC, evilrat wrote:
 The problem is that TypeInfo is not shared on Windows, which is 
 actually roots deeper in the other problems with "sharing".
 Unfortunately I cannot provide you with details, but this 
 situation is well known long standing issue.
It isn't just the typeinfo too, the catch tables are also not merged. https://github.com/dlang/druntime/pull/2874 I wrote that like infinity years ago and it hacks some of the problems but like the typeinfo string compare is not generally correct and idk how to solve that part without hacking the compiler too.
Mar 14 2021
prev sibling parent frame <frame86 live.com> writes:
On Sunday, 14 March 2021 at 12:27:17 UTC, evilrat wrote:
 On Sunday, 14 March 2021 at 09:35:40 UTC, frame wrote:
 As a workaround maybe you could introduce special 
 DLLWrapperException with reference to original exception using 
 cast hack?
This is unsatisfying. I want to switch-catch the exceptions also via their types.
Mar 14 2021
prev sibling parent reply Imperatorn <johan_forsberg_86 hotmail.com> writes:
On Sunday, 14 March 2021 at 09:35:40 UTC, frame wrote:
 I know I cannot throw exceptions from a DLL, it will crash. So 
 I currently use a wrapper that collects exceptions and pick it 
 up if the wrapper method returns a failure state.

 As I know what type of exception will be thrown, I can copy all 
 important data to a new exception object and then throwing it 
 in the current context.

 However, I wonder if there is way to copy the exception data 
 via Throwable interface direct because checking for types via 
 typeid() and string comparsion is just meh.

 It is possible to fetch the exception data:

 // Throwable e;

 // this returns null in the program (but works in a debugger 
 watch):
 MyExceptionObj imported = cast(MyExceptionObj)e;

 // this actually works:
 MyExceptionObj imported = cast(MyExceptionObj) cast(void*)e;

 But for some reason throwing this object directly would crash.

 Is there are way to copy the exception data in a new Throwable 
 instance that can be thrown from the current context? Or can 
 the runtime be tricked by overwriting the TypeInfo in memory? 
 (I don't know exactly what the actual problem is.)
In the past I've used a two patterns which are kinda wierd but. Basically the first is returning a tuple w value and exception and just check it, kinda like Go. The second approach is to have a function u can call to get the latest ex, kinda like GetLastError win api
Mar 14 2021
parent frame <frame86 live.com> writes:
On Sunday, 14 March 2021 at 15:45:19 UTC, Imperatorn wrote:
 On Sunday, 14 March 2021 at 09:35:40 UTC, frame wrote:
 In the past I've used a two patterns which are kinda wierd but. 
 Basically the first is returning a tuple w value and exception 
 and just check it, kinda like Go. The second approach is to 
 have a function u can call to get the latest ex, kinda like 
 GetLastError win api
I think that is like my pattern actually. I can call a method for the latest exception. But to throw it I need to create a new instance and copy the data. I would like to have a proxy that can copy the data into a new instance without manually checking for the type via string comparison. I don't care for the call trace, this data is collected and saved as string before the DLL function returns. The idea is to scan the TypeInfo memory area of the exception and replace it with the one that is valid for current context so the object can be recognized later and set the call stack reference or whatever the crash causes to null. Alternatively a new instance should be created and data just copied automatically.
Mar 14 2021