Pim Schellart
Pim Schellart

Reputation: 735

Most elegant way for SWIG wrapped C library to raise exceptions

I have recently converted a library, I originally wrote in C++ with Boost Python wrapping, to C with SWIG wrapping to support more languages. I switched from C++ to C because the library consists only of a set of functions and I also want the library to be callable from C (without having to compile the whole program with a C++ compiler). However there is one thing that was not easy to port, a very small subset of the functions needs the ability to report errors back. In C++/Boost Python that was very elegantly accomplished with throw and exception translation.

What would be the most elegant way (on both the C and wrapped language side) to have a subset of functions report errors?

Upvotes: 4

Views: 1269

Answers (2)

Mike T
Mike T

Reputation: 86

This is how I do it. the %{...%} block inserts it's contents to the wrapper file. The %exception block is SWIG's exception handling, and runs after each function call to check if there was an error and throw an exception with PyErr_SetString if there was. Then, simply call "set_err("Error msg"); from your C function if you want to throw an exception.

%{
    /* Exception helpers */
    static int swig_c_error_num = 0;
    static char swig_c_err_msg[256];

    const char *err_occurred()
    {
        if (swig_c_error_num) {
            swig_c_error_num = 0;
            return (const char*)swig_c_err_msg;
        }
        return NULL;
    }

    void set_err(const char *msg)
    {
        swig_c_error_num = 1;
        strncpy(swig_c_err_msg, msg, 256);
    }
%}

%exception {
    const char *err;
    $action
    if (err = err_occurred()) {
        PyErr_SetString(PyExc_RuntimeError, err);
        return NULL;
    }
}

Alternatively if your C library uses a standard set of return codes you can replace this mechanism with a check of your function's return code in the %exception block.

%exception {
    int rc;
    rc = $action;

    if (rc == ERR) {
        PyErr_SetString(PyExc_RuntimeError, <err msg>);
        return NULL;
    }
}

Upvotes: 5

Yuriy Y. Yermilov
Yuriy Y. Yermilov

Reputation: 133

Take a look at Chapter 4 in C Interfaces and Implementations by Richard R. Hanson.

Upvotes: 0

Related Questions