Reputation: 735
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
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
Reputation: 133
Take a look at Chapter 4 in C Interfaces and Implementations by Richard R. Hanson.
Upvotes: 0