Ok, that is an interesting idea. I'd have to see how it fits into the whole process because I thought you had to do the set_source before you could to the cdef.
Anyway, I implemented half of what I'm suggesting. My fork:
https://bitbucket.org/CrazyCasta/cffi/commits/8cbeed427476a5cc10dfdee9734a86fb475c3412 provides a way of calling setjmp before the call and then converting setjmp's into specific exceptions if they were triggered. Here is some code to test:
(ve) $ cat test_build.py
from cffi import FFI
ffi = FFI()
ffi.set_source("setjmp",
"""
#include <setjmp.h>
jmp_buf my_jmp_buf;
jmp_buf *my_jmp_buf_p = &my_jmp_buf;
jmp_buf my_jmp_buf2;
jmp_buf *my_jmp_buf_p2 = &my_jmp_buf2;
void my_longjmp() {
longjmp(my_jmp_buf, 1);
}
void my_longjmp2() {
longjmp(my_jmp_buf2, 1);
}
""", extra_compile_args=["-g"])
types = """
typedef ... jmp_buf;
static const jmp_buf *my_jmp_buf_p;
static const jmp_buf *my_jmp_buf_p2;
void my_longjmp();
void my_longjmp2();
"""
ffi.cdef(types)
ffi.compile()
(ve) $ cat test_run.py
from setjmp import ffi, lib
class MyException(Exception):
pass
class MyException2(Exception):
pass
ffi._exception_setjmp_map = {lib.my_jmp_buf_p: MyException,
lib.my_jmp_buf_p2: MyException2}
print "About to call longjmp, expect more messages, if not test has failed."
try:
lib.my_longjmp()
print "No exception thrown, fail"
except MyException:
print "Caught MyException, pass"
except:
print "Caught some other exception, fail"
print "About to call longjmp2, expect more messages, if not test has failed."
try:
lib.my_longjmp2()
print "No exception thrown, fail"
except MyException2:
print "Caught MyException2, pass"
except:
print "Caught some other exception, fail"
(ve) $ python test_build.py
(ve) $ python test_run.py
About to call longjmp, expect more messages, if not test has failed.
setjmp caught
Caught MyException, pass
About to call longjmp2, expect more messages, if not test has failed.
setjmp caught
Caught MyException2, pass
Notes:
* I've only tested this with python2.7, it might well be broken with python3.x and unless pypy has artificial intelligence it won't work at all.
* This is a demonstration of the idea, I'm not suggesting that the API w/ this _exception_setjmp_map attribute be used. Also, things like where code is placed, style, etc I'm open to suggestions.
* I've only tested this on windows, I noticed some ifdefs relating to WIN32 and that would probably need to get handled.
* The code changes only somewhat affect ffi's that don't include a jmp_buf declaration and this could be extended to make it exactly the same as it previously was if there are no jmp_buf's (to avoid performance degradation if that's a concern).
* This doesn't include the throw exception in callback->longjmp in C. Hopefully you'll believe that that's at least a bit easier then handling the setjmp code.
Alex