?
Solved

How to map/marshall native exceptions into managed exceptions?

Posted on 2009-05-01
4
Medium Priority
?
2,343 Views
Last Modified: 2013-12-17
Hello,

I am creating a DLL that contains a native "C++" class "CR", and a managed wrapper class "CM" that wraps around CR via a pointer.  

CR defines and uses "C++" native exceptions.  

In CM, I have created managed versions of the unmanaged exceptions in CR.

The methods in CM that invoke, via CR's pointer, methods in the unmanaged code of CR have try...catch...finally.  For each possible native exception that could be thrown through from the unmanaged method, I have placed a catch.  Inside the catch, I simply throw the managed version of the native exception.  Basically, this is how I am providing the mapping from unmanaged to managed exceptions.  

If I do not catch an unmanaged exception, I expect that an SEH exception will be generated.

From what I have read, this process should work, but whenever I force my native code to throw an unmanaged exception, what I catch in my CM wrapper class is an SEH exception.  Arggg...  So much for me understanding things!  :P

So, I am hoping that someone can tell me the best practices way to marshall exceptions between managed and unmanaged code...  Must I replace my native "C++" code with SEH (hope not)?  Is there an interop method that provides mapping that I must override?  Should I just define managed exceptions in my unmanaged code (i would prefer to keep the worlds separate, if possible)?

I would sincerely appreciate you help with these questions...

Thanks,

Mike
0
Comment
Question by:mjgardne
  • 2
  • 2
4 Comments
 

Author Comment

by:mjgardne
ID: 24287823
So, I've done more testing and the code snippet contains my results and comments...  I am still at a loss as to what is the best practice manner for handling exceptions that cross unmanaged->managed boundaries, and hope that I get some guidance from others who have wrestled with this question.

Thanks,

Mike


try
{
    // From managed, C++...
    // Calling Test() in the native C++, unmanaged code to make the native, unmanaged code throw one of our C++ exceptions,
    // which are subclassed from std::exception.
    cmr->Test();
}
 
	// This is the C++ base exception class in the native, unmanaged code, and it is a subclass of std::exception
	// Although, Test() throws this exception from the native code, it 
	// never reaches the catch statement.
	catch (CRegistryException& ex)
	{
		int a=0;
	}
 
	// So, next I try to catch any kind of C++ native exception.  Although
	// Test() in the native code throws a subclass of std::exception, it
	// never reaches this catch statement.
	catch (std::exception& ex)
	{
		int a=0;
	}
 
	// For some reason, when Test() throws a subclassed C++ std::exception, it
	// can be caught here.  When I look at ex in the debugger, it contains
	// two fields: std::exception and message.  Message is a member is
	// my native exception subclass so I can pass along a message when it
	// is thrown.  std::exception contains two fields: _m_doFree and _m_what.
	//
	// When I did a    throw gcnew System::Exception("Hi")     from the unmanaged code, it
	// was caught here, but ex was "undefined".  When I subclassed from 
	// System::Exception and tried to catch the subclass, it caught it, but
	// ex was undefined.  Why is ex undefined in both cases?  In my 
	// application, all I care about is catching the unmanaged exceptions so
	// I can map them to managed ones with localized error messages.  So,
	// I may be able to live with throwing managed exceptions from native
	// code, but I still would like to know what is best practice, why
	// are unmanaged, C++ std::exceptions being caught by catch(Exception ^ex),
	// and why ex has an "undefined" value.  Arggg...  Why is this so
	// difficult!  :)
	catch(Exception ^ex)
	{
		int a=0;
	}
 
	// We never reach this point.
	catch(...)
	{
		int a =0;
	}

Open in new window

0
 
LVL 19

Expert Comment

by:LordOfPorts
ID: 24297152
Is the behavior different if you catch an exception of type System.Runtime.InteropServices.SEHException http://msdn.microsoft.com/en-us/library/aa330529(VS.71).aspx in the managed code?
0
 
LVL 19

Expert Comment

by:LordOfPorts
ID: 24299039
Here is also one article that describes using vectored exception handling to convert Win32 and C++ exceptions to managed exceptions: http://blogs.microsoft.co.il/blogs/sasha/archive/2008/08/20/converting-win32-and-c-exceptions-to-managed-exceptions.aspx 
0
 

Accepted Solution

by:
mjgardne earned 0 total points
ID: 24302044
Hi LordOfPorts,

Thank you for the great articles about vectored exception handling...  When I was Googling for info, I found bits and pieces about this method, but nothing that drew it all together like your suggestion did.  Conceptually, this seems like it would be a valid alternative for passing native exceptions to managed code.  Our application is built upon a layer made of 7 DLLs.  Each DLL has an unmanaged class doing low level work, and a managed class that acts as the interface to higher application levels.  From what I have read, it seems that our entire application would have register the handler and in it is where the translations would happen...  From a reusability and principle of locality point of view, it would be nice to catch them on the individual DLL level...  I have no experience with vectored exceptions, so I will have to see whether they will work at a lower level than an application.  To be honest, from my testing, it appears that I can simply convert my unmanaged exceptions that subclass std::exception to managed exceptions that subclass System::Exception.  When I threw them from natve code, I successfully caught them, by name, in the managed code without any extra work.  I have read many times that it is not an issue to mix natve and managed types, so maybe this is why it works well.  The thing that I do not know is whether this is the preferred solution.  It would work for my needs, but what is the best practice and most current method?  There seem to be thousands of people working on similar projects, but I am amazed that I cannot find a common solution to my question.  Your solution is very interesting, but the KISS principle favors mine...  :P   Anyway, thank you for your great reference and I will try it out over the next few days...  If I hit some walls, I will probably wimp out and simple throw managed exceptions from my unmanaged code.

Thanks and have a great Tuesday!

Mike
0

Featured Post

Efficient way to get backups off site to Azure

This user guide provides instructions on how to deploy and configure both a StoneFly Scale Out NAS Enterprise Cloud Drive virtual machine and Veeam Cloud Connect in the Microsoft Azure Cloud.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

It seems a simple enough task, yet I see repeated questions asking how to do it: how to pass data between two forms. In this article, I will show you the different mechanisms available for you to do just that. This article is directed towards the .N…
This article shows how to deploy dynamic backgrounds to computers depending on the aspect ratio of display
Is your data getting by on basic protection measures? In today’s climate of debilitating malware and ransomware—like WannaCry—that may not be enough. You need to establish more than basics, like a recovery plan that protects both data and endpoints.…
Is your OST file inaccessible, Need to transfer OST file from one computer to another? Want to convert OST file to PST? If the answer to any of the above question is yes, then look no further. With the help of Stellar OST to PST Converter, you can e…
Suggested Courses

809 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question