Statically Typed

because Hindley-Milner rocks

Swig, Python and C++ Exceptions (cont’)


Greater success today with implementing exception passing between Python and C++.  Learned a few gotchas, used a tip from SO, and generally all around excited to continue with the project full steam ahead!  Sounds like a good day, no?  It was.

Python -> C++

I was having the hardest time getting the C++ code to recognize hand crafted exception classes as I said below.  They kept being converted to Swig::DirectorMethodException.  However, following a tip I made a C++ class especially for throwing C++ exceptions in C++.

struct ExceptionFactory{
    void throwAlarm() const { throw Alarm(); }
    void throwNormal() const { throw std::exception(); }
    void throwTilde() const { throw int(4); }
};

And at the Python level I implemented my Foo class as

class FooRedux(Foo):
    def __init__(self):
        Foo.__init__(self)
    def getInt(self):
        return 6
    def throw(self):
        myExceptionFactory.raiseAlarm()

which did the trick for our own declared C++ exceptions.  (Update:  This won’t work.)

Next up was getting the C++ code to recognize Python exceptions.  This couldn’t be easier.  Someone had already thought of it and added the functionality to SWIG.  It involved inserting a small amount of code into the *.i file.

%feature("director:exception"){
    ( $error != NULL ){
        throw Swig::DirectorMethodException();
    }
}

Bingo, done.

C++ -> Python

Getting Python to recognize our own home grown exceptions came with a small surprise.  First we had to put in more code into the *.i file to tell SWIG how to communicate back to the Python code.

%exception(Python){
    try{
        $action
    }
    catch( Alarm &ex ){
        PyErr_SetString( PyExc_RuntimeError, ex.msg() );
    }
    catch( std::exception &ex ){
        PyErr_SetString( PyExc_RuntimeError, ex.what() );
    }
    catch( Swig::DirectorException ){
        PyErr_SetString( PyExc_RuntimeError, "Swig::DirectorException thrown" );
    }
    catch( ... ){
        Swig_Fail;
    }
}
%include exception.i

Looks verbose but worth the trouble.  Once we fired up IDLE we had to make sure to do one more thing… not import Alarm!  That’s right, I had to specifically import every object I wanted to use except for my own defined exception.  If it was imported, it caused a crash the minute the C++ code attempted to throw it.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Information

This entry was posted on May 26, 2010 by in Uncategorized.
%d bloggers like this: