I am calling a C function from a DLL using Python's CFFI.
from CFFI import FFI
my_ffi = FFI()
my_dll = my_ffi.dlopen(my_dll_path)
my_ffi.cdef('int my_func();')
my_c_int = my_dll.my_func()
Occasionally, the C function will crash, throw an exception, or a combination of those. This has typically caused the Python script calling the C function to terminate.
I would like to be able to do something like this:
try:
my_c_int = my_dll.my_func()
except SomeKindsOfExceptionsIncludingTheForeignFunctionCrashing:
handle_exception()
Is it possible to handle exceptions raised by the foreign function as well as crashes in the foreign function? If so, how best could it be accomplished?
edit: Specifically, I would like to handle exceptions raised during the execution of code in the foreign function as well as libraries it uses. I would not like to catch and ignore hardware exceptions. A typically exception I am dealing with is caused by a socket getting unexpectedly disconnected.
I have considered calling the C function in a separate thread and monitoring that thread for a timeout. However, the C function implements part of the loss function of an optimizer, so I would like to avoid the overhead of starting a new thread each time I call the C function. Additionally, a new thread is messy and it feels like there should be an easier way to do this.
I am separately looking into ways to reduce the amount of unusual behavior coming from my DLL, though that may not come to fruition.
edit: SEH was suggested in the comments, however as I understand it, this would occur in the foreign function rather than on the Python side. My goal is to be able to use Python to handle such exceptions. Here is a response to a thread which seems to suggest that the ctypes module does not support SEH:
If an OS exception isn’t handled at a low level by the interpreter or an extension module, the process crashes hard.
However, I am using the CFFI module which may have somewhat different behavior.
You can indirectly use CFFI to call C++ code and catch C++ exceptions, by writing your own C wrapper around the C++ code. To do that, you need to use CFFI in API mode and write the wrapper in the set_source()
part; and then you call this C wrapper using CFFI.
You can also use the CPython C API directly, but it requires the same C wrappers anyway: neither solution does anything sane about C++ exceptions, so you have to catch and convert them.