I cannot throw exceptions through dlsym. I am using dlsym to download a cythonized python file. Below I gave a minimal working example so you can try it yourself:
I have a pyx file, c_fun.pyx, which I compile into a C file using Cython. Then I use dlsym to load in such a file in another program, say use_fun.C ++. You can use. /compile.sh to compile files. By doing. / test program crashes with a segmentation error.
#c_fun.pyx: cdef public double _myfunction(double x) except*: a=1/0 # This does not propagate an exception. Comment to make the example work return x**2-x # This works. #use_fun.c++ #include <dlfcn.h> #include <stdio.h> int main(int argc, char **argv) { void* handle = dlopen("./c_fun.so", RTLD_NOW | RTLD_GLOBAL); if(handle==NULL) { printf("%s \nat line number: %i\n",dlerror(),__LINE__); return; } double (*f)(double) = (double (*)(double))dlsym(handle, "_myfunction"); if(f==NULL) { printf("%s\n",dlerror()); return; } double res = 0; try { res = (*f)((double)99); } catch(char *err) { printf("Got exception: %s.\n", err); } printf("res = %f\n", res); } #setup.py from distutils.core import setup from distutils.extension import Extension from Cython.Distutils import build_ext ext_modules = [Extension("c_fun", ["c_fun.pyx"], libraries = ['python2.7'], extra_compile_args= ['-fexceptions'])] setup( name = 'Hello world app', cmdclass = {'build_ext': build_ext}, ext_modules = ext_modules ) # compile.sh python setup.py build_ext --inplace echo "gcc use_fun.c++ -g -O0 -o test -ldl" g++ use_fun.c++ -g -O0 -o test -ldl
At first I tried without "except *" at the end of my function and without the "-fexceptions" compiler flag. But adding them does not change behavior. gdb doesn’t even let me solve the problem and says: “Cannot find new threads: a common mistake” I looked on the Internet for exception handling in conjunction with dlsym, but found little information.
The rest of the story. To make it more complex, this use_fun file is actually. C ++ is the Python module I imported. So: I use Python to load in the use_fun module, and _myfunction is called in this C ++ module. But also, I cannot get the correct exception handling. However, in this case, I successfully used gdb to enter the C code and saw that PyErr_Format was successfully called. But the error does not start and does not fall into C ++ code.
Please note that in order to set the _myfunction file, I specified the keyword "public" in the pyx file. Without it, smoothing the name will cause the dlsym function call to fail. I tried to find documentation on these two links:
http://docs.cython.org/src/userguide/external_C_code.html#using-cython-declarations-from-c
http://docs.cython.org/src/userguide/language_basics.html#error-return-values
Edit: I found a solution. I will keep the original question above so that it can help others. There were essentially 2 problems
1) Of course, since C has no exceptions, it was wrong to set try / catch on a function! What works is to check if an error has occurred in Python using PyErr_Occurred ().
2) Since cython generates a module, it must be initialized before you can use it correctly. This means: a call to Py_Initialize / Py_Finalize, as well as a call to the init_cfun method.
The solution is shown below:
#include "Python.h" #include <dlfcn.h> #include <stdio.h> int main(int argc, char **argv) { Py_Initialize(); void* handle = dlopen("./c_fun.so", RTLD_NOW | RTLD_GLOBAL); if(handle==NULL) { printf("%s \nat line number: %i\n",dlerror(),__LINE__); return -1; } void (*init_func)(); *(void**)(&init_func) = dlsym(handle, "initc_fun"); init_func(); double (*f)(double) = (double (*)(double))dlsym(handle, "_myfunction"); if(f==NULL) { printf("%s\n",dlerror()); return -1; } double res = 0; res = (*f)((double)99); if(PyErr_Occurred()) { PyErr_Print(); } printf("res = %f\n", res); Py_Finalize(); return 0; }