ThrowTheSwitch / CException

Lightweight exception implementation for C
http://throwtheswitch.org
MIT License
320 stars 64 forks source link

Is there a safe procedure for C++ interaction #8

Closed sbseltzer closed 4 years ago

sbseltzer commented 7 years ago

Is there a safe way of wrapping frameworks using CException with C++? I realize C jumps subvert stack unwinding, causing undefined behaviour. Still, the project I'm working on will most certainly be wrapped in C++ by users.

What I'm interested in is if there's a pattern that ensures safe integration with C++. Ideally, there could be some conversion from CExceptions to C++ exceptions.

I imagine no C++ class instances would be allowed to instantiate or destruct themselves in a Try block. I also imagine it would be absolutely necessary to ensure no CExceptions escape upwards into C++ land, which means there would need to be very tightly scoped wrapping. I also imagine it would be illegal to leverage CException at the C++ level as a stand-in for C++ exceptions. Am I on the right track with this line of thought?

mvandervoord commented 4 years ago

I apologize to anyone waiting on this question. This project almost never gets Issues posted and I didn't notice the notification when it did.

This is an excellent question, but I'm not sure I have a clean answer for you.

I think I would start with making sure I had CEXCEPTION_NO_CATCH_HANDLER specified. This will make it so that any uncaught exceptions are channeled somewhere. This function handler could then throw a C++ exception, call a callback, or do whatever interaction you're hoping for.

I agree with most of your points. You wouldn't want to allow any C++ instances to be created / destroyed within a Try block, unless you had a method of tracking them (one of the add-on garbage handlers might handle this cleanly?)

The last point isn't necessarily true. I know people have used CException as a replacement for C++ Exceptions and had their compiler disable C++ Exceptions completely, because CException is so much lower overhead. This is almost universally for embedded targets. You'd have to be incredibly careful doing this sort of thing, primarily because of the object creation rules mentioned above... but these types of applications are also the same applications that often require no dynamic memory, so all the objects are defined up-front. This makes it a decent match.