I am writing a library in C++ which uses an older C API. The client of my library can specify callback functions, which are indirectly called through my library which is called through the C API. This means that all exceptions in the client callbacks must be handled.
My question is this: how can I catch the exception on one side of the boundary and re-throw it once the C API boundary has been recrossed and the execution is back in C++ land so that the exception can be handled by client code?
With C++11 we could use:
std::exception_ptr active_exception;
try
{
// call code which may throw exceptions
}
catch (...)
{
// an exception is thrown. save it for future re-throwing.
active_exception = std::current_exception();
}
// call C code
...
// back to C++, re-throw the exception if needed.
if (active_exception)
std::rethrow_exception(active_exception);
Before C++11 these can still be used via Boost Exception.
Some environments support this more or less directly.
For instance, if you enable structured exception handling and C++ exceptions through the /EH
compiler switch, you can have C++ exceptions implemented over Microsoft's structured exception handling ("exceptions" for C). Provided these options are set when compiling all your code (the C++ at each end and the C in the middle) stack unwinding will "work".
However, this is almost always a Bad Idea (TM). Why, you ask? Consider that the piece of C code in the middle is:
WaitForSingleObject(mutex, ...);
invoke_cxx_callback(...);
ReleaseMutex(mutex);
And that the invoke_cxx_callback()
(....drum roll...) invokes your C++ code that throws an exception. You will leak a mutex lock. Ouch.
You see, the thing is that most C code is not written to handle C++-style stack unwinding at any moment in a function's execution. Moreover, it lacks destructors, so it doesn't have RAII to protect itself from exceptions.
Kenny TM has a solution for C++11 and Boost-based projects. xxbbcc has a more general, albeit more tedious solution for the general case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With