The situation is that I have a dynamic library written in C++ that is wrapped for Python by another dynamic library, also written in C++ (generated by SIP to be specific). The first dynamic library defines a function do_raise, which throws an exception RaiserError, a subclass of std::exception. The second dynamic library, in wrapping do_raise, tries to catch RaiserError in order to translate it to a Python exception.

Building with Visual C++, everything works as expected and RaiserError is caught correctly. Using g++ on Linux however, RaiserError is not caught. If I try to catch std::exception instead (RaiserError's baseclass), it works. What goes wrong here? Do the two libraries have different notions of the RaiserError type, since it does not get recognized by the catch block?

For testing I also write a small executable which calls do_raise in the C++ library, and here I am able to catch RaiserError even with g++.

There must be differences between the real app and your test app. At least one of them is critical. From what you wrote, it's very hard for us to tell.
–
sbiSep 22 '09 at 8:47

I use one version of g++, the one shipped with Ubuntu 9.04, i.e., 4.3.3. The difference with the test app is that it is also written in C++, not Python. I have since been able to make a small Python program work, since I changed a build parameter (to do with symbol export) for the Python wrapper library. However, my real application still doesn't work, so this is another indication that the issue is down to incompatible build parameters.
–
Arve KnudsenSep 28 '09 at 17:26

I believe that GCC uses some kind of pointer to the type information and if it does not match the pointer, then the types are not the same.

This sounds like one of the cases where Microsoft C++ falls back to string comparisons of type information (slow but works). That will not help you with GCC.

You might try making sure that the exception class is not hidden and that the typeinfo is visible in the ELF .so file. Try to make sure that the type is defined in only one .so.

Edit: I just thought of this: I believe ELF dynamic linkers are just fine with multiple copies of the typeinfo symbols and will choose a single copy to use. I think you can get multiple copies though if you linked some static code or did -Bsymbolic in one of the .so or executable files.

Do you know how the relevant symbols should look in the ELF libraries? As an example I have in my real project an exception "LoadImageError". In the defining/throwing library I have these typeinfo symbols: 000b9634 V typeinfo for igmUtil::LoadImageError 000a3d5c V typeinfo name for igmUtil::LoadImageError And in the Python wrapper library (trying to catch the exception): 000174b8 d DW.ref._ZTIN7igmUtil14LoadImageErrorE 00016540 V typeinfo for igmUtil::LoadImageError 00011e85 V typeinfo name for igmUtil::LoadImageError
–
Arve KnudsenSep 28 '09 at 17:30

I haven't previously had problems catching exceptions thrown by a .so, so can't speak to the other responses I've seen here.

Something unrelated to look for is whether any of your destructors might be throwing an exception: if you throw a new exception in a destructor while unwinding the stack throwing a first exception, your program will abort, independent of any wrapping try/catches. With g++, the error message looks the same as if you didn't catch the first exception. Carefully step through the unwinding of the stack to see if this might be happening to you.

As per other answers the problem is (more then likely) missing RTTI information in the .so's.

Try appending -Wl,-E to your compiler flags, this will cause the linker to export the needed type information.

VC++ uses string compares (as opposed to pointer compares) to match types (whilst dynamic casting, catching etc), this is slower at runtime but results in smaller dll's (because of less RTTI being exported in the dll's).

This will be reliable as long as your using the same compiler to compile your shared objects (or you use the vendor-neutral ABI, as available with g++ >= 4.3).