Cython weakref to cdef class 存储在 C 对象中
Cython weakref to cdef class stored in C object
我正在尝试为 linphone 库编写一个 Cython 包装器,但我遇到了一个问题:我想在 C 中存储代表我的 C 对象的 Python 对象的 weakref对象。
这是我的包装纸:
cdef void on_global_state_changed_cbs(LinphoneCore *lc, LinphoneGlobalState gstate, const char *message):
print('Internal Callback : ' + str(gstate) + ' : ' + message)
cbs = linphone_core_get_current_callbacks(lc)
callbacks = CoreCallbacks.from_ptr(cbs)
if callbacks.global_state_cb is not None:
core = Core.from_ptr(lc)
callbacks.global_state_cb(core, gstate, message)
ctypedef struct LinphoneCoreCbs:
pass
cdef class CoreCallbacks:
cdef object __weakref__
cdef LinphoneCoreCbs *ptr
cpdef global_state_cb
@staticmethod
cdef CoreCallbacks from_ptr(LinphoneCoreCbs *_ptr, take_ref = True):
cdef CoreCallbacks coreCbs
user_data = belle_sip_object_data_get(<belle_sip_object_t *>_ptr, 'python_user_data')
if user_data is not NULL:
tmpWRef = <object>user_data
print tmpWRef
coreCbs = tmpWRef()
if coreCbs is None:
coreCbs = CoreCallbacks.__new__(CoreCallbacks)
coreCbs.ptr = linphone_core_cbs_ref(_ptr) if take_ref else _ptr
else:
coreCbs = CoreCallbacks.__new__(CoreCallbacks)
coreCbs.ptr = linphone_core_cbs_ref(_ptr) if take_ref else _ptr
print coreCbs
wref = weakref.ref(coreCbs)
print wref
belle_sip_object_data_set(<belle_sip_object_t *>_ptr, 'python_user_data', <void *>wref, NULL)
linphone_core_cbs_set_global_state_changed(coreCbs.ptr, &on_global_state_changed_cbs)
return coreCbs
def __dealloc__(self):
print 'Dealloc ' + str(self)
if self.ptr is not NULL:
belle_sip_object_data_remove(<belle_sip_object_t *>self.ptr, 'python_user_data')
linphone_core_cbs_unref(self.ptr)
self.ptr = NULL
@property
def on_global_state_changed_cb(self):
return self.global_state_cb
@on_global_state_changed_cb.setter
def on_global_state_changed_cb(self, cb):
self.global_state_cb = cb
问题是当我从回调中调用 Core.from_ptr 时,tmpWRef 表示对象已死,因此创建了一个新对象。我在 dealloc 方法中添加了一个打印,我看到该对象还没有被释放。
我的测试程序:
def global_state(lc, state, message):
print ('External callback : ' + str(state) + ' -> ' + message)
f = Factory.get_instance()
c = f.create_core()
cbs = f.create_core_cbs()
cbs.on_global_state_changed_cb = global_state
c.add_callbacks(cbs)
c.start()
这是我的测试程序的示例输出:
<pylinphone.CoreCallbacks object at 0x7f7211fe6c80>
<weakref at 0x7f7212001368; to 'pylinphone.CoreCallbacks' at 0x7f7211fe6c80>
Internal Callback : 1 : Starting up
<weakref at 0x7f7212001368; dead>
<pylinphone.CoreCallbacks object at 0x7f7212000460>
<weakref at 0x7f7212001368; to 'pylinphone.CoreCallbacks' at 0x7f7212000460>
Dealloc <pylinphone.CoreCallbacks object at 0x7f7212000460>
[...]
Dealloc <pylinphone.CoreCallbacks object at 0x7f7211fe6c80>
感谢 DavidW,我发现了问题所在:weakref 没有被任何人持有。
我在我的 class 中添加了一个 cpdef wref 字段,现在它工作正常:)
我正在尝试为 linphone 库编写一个 Cython 包装器,但我遇到了一个问题:我想在 C 中存储代表我的 C 对象的 Python 对象的 weakref对象。
这是我的包装纸:
cdef void on_global_state_changed_cbs(LinphoneCore *lc, LinphoneGlobalState gstate, const char *message):
print('Internal Callback : ' + str(gstate) + ' : ' + message)
cbs = linphone_core_get_current_callbacks(lc)
callbacks = CoreCallbacks.from_ptr(cbs)
if callbacks.global_state_cb is not None:
core = Core.from_ptr(lc)
callbacks.global_state_cb(core, gstate, message)
ctypedef struct LinphoneCoreCbs:
pass
cdef class CoreCallbacks:
cdef object __weakref__
cdef LinphoneCoreCbs *ptr
cpdef global_state_cb
@staticmethod
cdef CoreCallbacks from_ptr(LinphoneCoreCbs *_ptr, take_ref = True):
cdef CoreCallbacks coreCbs
user_data = belle_sip_object_data_get(<belle_sip_object_t *>_ptr, 'python_user_data')
if user_data is not NULL:
tmpWRef = <object>user_data
print tmpWRef
coreCbs = tmpWRef()
if coreCbs is None:
coreCbs = CoreCallbacks.__new__(CoreCallbacks)
coreCbs.ptr = linphone_core_cbs_ref(_ptr) if take_ref else _ptr
else:
coreCbs = CoreCallbacks.__new__(CoreCallbacks)
coreCbs.ptr = linphone_core_cbs_ref(_ptr) if take_ref else _ptr
print coreCbs
wref = weakref.ref(coreCbs)
print wref
belle_sip_object_data_set(<belle_sip_object_t *>_ptr, 'python_user_data', <void *>wref, NULL)
linphone_core_cbs_set_global_state_changed(coreCbs.ptr, &on_global_state_changed_cbs)
return coreCbs
def __dealloc__(self):
print 'Dealloc ' + str(self)
if self.ptr is not NULL:
belle_sip_object_data_remove(<belle_sip_object_t *>self.ptr, 'python_user_data')
linphone_core_cbs_unref(self.ptr)
self.ptr = NULL
@property
def on_global_state_changed_cb(self):
return self.global_state_cb
@on_global_state_changed_cb.setter
def on_global_state_changed_cb(self, cb):
self.global_state_cb = cb
问题是当我从回调中调用 Core.from_ptr 时,tmpWRef 表示对象已死,因此创建了一个新对象。我在 dealloc 方法中添加了一个打印,我看到该对象还没有被释放。
我的测试程序:
def global_state(lc, state, message):
print ('External callback : ' + str(state) + ' -> ' + message)
f = Factory.get_instance()
c = f.create_core()
cbs = f.create_core_cbs()
cbs.on_global_state_changed_cb = global_state
c.add_callbacks(cbs)
c.start()
这是我的测试程序的示例输出:
<pylinphone.CoreCallbacks object at 0x7f7211fe6c80>
<weakref at 0x7f7212001368; to 'pylinphone.CoreCallbacks' at 0x7f7211fe6c80>
Internal Callback : 1 : Starting up
<weakref at 0x7f7212001368; dead>
<pylinphone.CoreCallbacks object at 0x7f7212000460>
<weakref at 0x7f7212001368; to 'pylinphone.CoreCallbacks' at 0x7f7212000460>
Dealloc <pylinphone.CoreCallbacks object at 0x7f7212000460>
[...]
Dealloc <pylinphone.CoreCallbacks object at 0x7f7211fe6c80>
感谢 DavidW,我发现了问题所在:weakref 没有被任何人持有。 我在我的 class 中添加了一个 cpdef wref 字段,现在它工作正常:)