Error handling in C librariesΒΆ
Some C libraries can produce errors and use some sort of callback mechanism to report errors: an external error handling function needs to be set up which will be called by the C library if an error occurs.
The function sig_error()
can be used to deal with these errors. This
function may only be called within a sig_on()
block (otherwise the Python
interpreter will crash hard) after raising a Python exception. You need to use
the Python/C API for this
and call sig_error()
after calling some variant of PyErr_SetObject()
.
Even within Cython, you cannot use the raise
statement, because then the
sig_error()
will never be executed. The call to sig_error()
will use the
sig_on()
machinery such that the exception will be seen by sig_on()
.
A typical error handler implemented in Cython would look as follows:
from cysignals.signals cimport sig_error
from cpython.exc cimport PyErr_SetString
cdef void error_handler(char *msg):
PyErr_SetString(RuntimeError, msg)
sig_error()
Exceptions which are raised this way can be handled as usual by putting
the sig_on()
in a try
/except
block.
For example, the package cypari2
provides a wrapper around the number theory library PARI/GP.
The error handler
has a callback which turns errors from PARI/GP
into Python exceptions of type PariError
.
This can be handled as follows:
from cysignals.signals cimport sig_on, sig_off
def handle_pari_error():
try:
sig_on() # This must be INSIDE the try
# (call to PARI)
sig_off()
except PariError:
# (handle error)
SageMath uses this mechanism for libGAP, GLPK, NTL and PARI.