Hi all,
I'm wrapping a C++ class from cython. The class constructor takes a callback as an argument, and the callback can be later called via a call() method. The call() method is declared in cython as except*. I'm passing a cython function as a callback, which internally calls a python function. The cython function passed as a callback is also declared as
except.
-------------- caller.hpp
-------------
typedef void (*CallBack)(void);
class Caller
{
public:
Caller(CallBack cb) : m_cb(cb), m_count(0) {};
void call(void) { m_cb(); m_count++; }
CallBack m_cb;
unsigned m_count;
};
--------------
-------------- caller.pyx
-------------
# distutils: language = c++
cdef extern from "caller.hpp":
ctypedef void (*CallBack)() except*;
cdef cppclass Caller:
Caller(CallBack cb)
void call() except*
unsigned m_count
_py_callback = None
cdef void c_callback() except*:
if _py_callback:
_py_callback()
cdef class PyCaller():
cdef Caller *p
def __cinit__(self, py_callback):
global _py_callback
_py_callback = py_callback
self.p = new Caller(c_callback)
def __dealloc__(self):
del self.p
def call(self):
self.p.call()
def get_count(self):
return self.p.m_count
--------------
If the python callback raises an exception, I'm expecting the C++ code execution to stop, i.e., m_count++ not to be executed. However, testing with:
-------------- test_caller.py
-------------
from pycaller import PyCaller
def py_callback():
assert 0
obj = PyCaller(py_callback)
try:
obj.call()
except AssertionError as e:
print("Yay, exception caught..")
try:
assert obj.get_count() == 0
except AssertionError as e:
print("Doh, execution didn't stop..")
else:
print("Yay, execution did stop..")
else:
print("Doh, exception not caught..")
--------------
I get as a result:
>python test_caller.py
Yay, exception caught..
Doh, execution didn't stop..
meaning that execution didn't stop. Am I missing something? Is my expectation of code stopping after python exception raised correct?
Cheers,
Marco