I'm not asking if it is safe for a C++ exception to propagate through C code, nor what happens when such thing occurs. I have read the following questions in SO(1, 2, 3) and this FAQ. I'm asking how to proceed to :
- Avoid leaking any C++ exception toward C code (this implies catching all exceptions in the C++ land before calling C code)
- Also be able to catch the exceptions outside the C code (in a higher C++ code).
Let me illustrate my idea :
Say libfoo
is a C library, that I want to use in my bar
C++ program. libfoo
needs a callback function foo_callback
that I must provide. The functions and methods used in my callback may throw an exception, so I wrote :
void my_callback(void)
{
try
{
// Do processing here.
}
catch(...)
{
// Catch anything to prevent an exception reaching C code.
// Fortunately, libfoo provides a foo_error function to
// signal errors and stop processing.
foo_error() ;
}
}
And then I use my callback as shown below :
// The bar program.
int main()
{
// Use libfoo function to set the desired callback
foo_set_callback(&my_callback) ;
// Start processing. This libfoo function uses internally my_callback.
foo_process() ;
// Check for errors
if( foo_ok() )
{
// Hurray !
}
else
{
// Something gone wrong.
// Unfortunately, we lost the exception that caused the error :(
}
}
What I want is to be able to catch the exceptions thrown from my_callback
in the main
function, without having the exception propagating through libfoo
(Yes, it's a sort of quantum exception experimenting quantum tunnelling through C code).
So the code I would love to use :
void my_callback(void)
{
try
{
// Do processing here.
}
catch(...)
{
// Catch anything to prevent an exception reaching C code.
// We save the exception using (the magic) ExceptionHolder.
ExceptionHolder::Hold() ;
// Call foo_error function to signal errors and stop processing.
foo_error() ;
}
}
// The bar program.
int main()
{
// Use libfoo function to set the desired callback
foo_set_callback(&my_callback) ;
try
{
// Start processing. This libfoo function uses internally my_callback.
foo_process() ;
// Once gone out of the C land, release any hold exception.
ExceptionHolder::Release() ;
}
catch(exception & e)
{
// Something gone wrong.
// Fortunately, we can handle it in some manner.
}
catch( /*something else */ )
{
}
// ...
}
Given the following constraints :
libfoo
is source-closed, written in C and provided in compiled format from a vendor. Tests conducted on the library showed that exceptions cannot propagate through it. I have no access to the source files nor I can obtain a compiled version that supports exceptions.- The callback function makes extensive use of C++ code that uses exceptions. All the error handling is built around the exception mechanism. In no way I can simply use the code that swallows all exceptions.
- No multithreading involved.
- No c++0x support.
My questions :
- Is it already solved by some library or some C++ magic (like
boost
), or even c++0x ? - If not, how can I write an ExceptionHolder that works with any exception type ? I'm confortable with C++ but I haven't found a way to write a reliable and easy to use ExceptionHolder that works with any exception type.
Many thanks for any advice !
EDIT : I added a response with a little implementation of the exception holding/releasing mechanism. All critics or propositions are welcome.