diff --git a/pyopencl/_cffi.py b/pyopencl/_cffi.py index 953be862f73d33e2e44f282bd08a7ca55fe9ee4b..60cb2e69db6996ae4d52c8bc7655c8cd2fafaff4 100644 --- a/pyopencl/_cffi.py +++ b/pyopencl/_cffi.py @@ -187,9 +187,16 @@ def _py_deref(handle): except: pass -@_ffi.callback('void(void*)') +# TODO: +# Not sure if cffi always return the same address for the same object +# Unless it is, this function might return a different pointer from its input +# and should only be called once. +@_ffi.callback('void*(void*)') def _py_ref(handle): + obj = _ffi.from_handle(handle) + handle = _ffi.new_handle(obj) _pyrefs[handle] = handle + return handle @_ffi.callback('void(void*, cl_int)') def _py_call(handle, status): diff --git a/pyopencl/c_wrapper/wrap_cl_core.h b/pyopencl/c_wrapper/wrap_cl_core.h index 7069dcbc5695a72f1c85e6a9db83a0c5a9688ae6..5427fa3c3aa10cbff0491bf48f014bebff899c3a 100644 --- a/pyopencl/c_wrapper/wrap_cl_core.h +++ b/pyopencl/c_wrapper/wrap_cl_core.h @@ -48,7 +48,7 @@ typedef struct { int get_cl_version(); void free_pointer(void*); void free_pointer_array(void**, uint32_t size); -void set_py_funcs(int (*_gc)(), void (*_ref)(void*), void (*_deref)(void*), +void set_py_funcs(int (*_gc)(), void *(*_ref)(void*), void (*_deref)(void*), void (*_call)(void*, cl_int)); int have_gl(); diff --git a/pyopencl/cffi_cl.py b/pyopencl/cffi_cl.py index 29d2dec02686f5f4c3a259c956814f3be1743e2a..1ee6ac7399777c88e6d079a60923dbd147a721bc 100644 --- a/pyopencl/cffi_cl.py +++ b/pyopencl/cffi_cl.py @@ -847,7 +847,10 @@ def wait_for_events(wait_for): class NannyEvent(Event): def get_ward(self): - return _ffi.from_handle(_lib.nanny_event__get_ward(self.ptr)) + _handle = _lib.nanny_event__get_ward(self.ptr) + if _handle == _ffi.NULL: + return + return _ffi.from_handle(_handle) # TODO # UserEvent diff --git a/src/c_wrapper/event.cpp b/src/c_wrapper/event.cpp index d7373af4fe13b2e108233b914c65bceb9e6678d0..61af726ceb1c58793ac2d6e37ae4e255c7ab1b58 100644 --- a/src/c_wrapper/event.cpp +++ b/src/c_wrapper/event.cpp @@ -143,11 +143,15 @@ event__set_callback(clobj_t _evt, cl_int type, void *pyobj) { auto evt = static_cast<event*>(_evt); return c_handle_error([&] { - evt->set_callback(type, [=] (cl_int status) { - py::call(pyobj, status); - py::deref(pyobj); - }); - py::ref(pyobj); + pyobj = py::ref(pyobj); + try { + evt->set_callback(type, [=] (cl_int status) { + py::call(pyobj, status); + py::deref(pyobj); + }); + } catch (...) { + py::deref(pyobj); + } }); } #endif diff --git a/src/c_wrapper/event.h b/src/c_wrapper/event.h index 7f3d6759a28d557d877f70e6225430cc6f7ac3dc..3bcd09025422e01f285c7f2f30babbc479ca96d0 100644 --- a/src/c_wrapper/event.h +++ b/src/c_wrapper/event.h @@ -43,10 +43,10 @@ private: void *m_ward; public: nanny_event(cl_event evt, bool retain, void *ward=nullptr) - : event(evt, retain), m_ward(ward) + : event(evt, retain), m_ward(nullptr) { if (ward) { - py::ref(ward); + m_ward = py::ref(ward); } } ~nanny_event(); diff --git a/src/c_wrapper/pyhelper.cpp b/src/c_wrapper/pyhelper.cpp index ca18c96a6f7baecd7330b9398f3e84aba44af27b..0000728ec0aa15dc1205f7dfaedaf1f95458ecae 100644 --- a/src/c_wrapper/pyhelper.cpp +++ b/src/c_wrapper/pyhelper.cpp @@ -4,7 +4,7 @@ namespace pyopencl { namespace py { WrapFunc<int()> gc; -WrapFunc<void(void*)> ref; +WrapFunc<void*(void*)> ref; WrapFunc<void(void*)> deref; WrapFunc<void(void*, cl_int)> call; } @@ -12,7 +12,7 @@ WrapFunc<void(void*, cl_int)> call; } void -set_py_funcs(int (*_gc)(), void (*_ref)(void*), void (*_deref)(void*), +set_py_funcs(int (*_gc)(), void *(*_ref)(void*), void (*_deref)(void*), void (*_call)(void*, cl_int)) { pyopencl::py::gc = _gc; diff --git a/src/c_wrapper/pyhelper.h b/src/c_wrapper/pyhelper.h index f336cbae27b1d88323cdb63006434478c76f747a..15a72f47383150232a56df1a1bedfcaf5bb4068c 100644 --- a/src/c_wrapper/pyhelper.h +++ b/src/c_wrapper/pyhelper.h @@ -37,7 +37,7 @@ public: namespace py { extern WrapFunc<int()> gc; -extern WrapFunc<void(void*)> ref; +extern WrapFunc<void*(void*)> ref; extern WrapFunc<void(void*)> deref; extern WrapFunc<void(void*, cl_int)> call; }