The most elegant way for a SWIG-wrapped C library to catch exceptions

I recently converted a library that I originally wrote in C ++ with Python Boost packaging, to C with SWIG packaging 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 called from C (without having to compile the entire program using the C ++ compiler). However, there is one thing that was not easy to carry, a very small part of the functions needs the ability to report errors. In C ++ / Boost, Python, which was very elegantly executed using throw and throw exceptions.

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

+4
source share
2 answers

This is how I do it. block% {...%} inserts its contents into the wrapper file. The% exception block excludes the SWIG exception handling and starts after each function call to check if there was an error, and threw an exception with PyErr_SetString, if any. Then just 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 by checking the function return code in the% exception block.

 %exception { int rc; rc = $action; if (rc == ERR) { PyErr_SetString(PyExc_RuntimeError, <err msg>); return NULL; } } 
+5
source

Take a look at Chapter 4 on Richard C. Hanson’s C Interfaces and Implementations.

0
source

Source: https://habr.com/ru/post/1345401/


All Articles