我正在实现一个基于cython的C ++库接口。我实现了一个与普通函数一起工作的回调系统,但在传入绑定方法时却奇怪地失败了。这是我的cython代码的一部分:
cdef extern from "VolumeHapticTool.h":
cdef cppclass HDButtonEvent:
bool isPressed()
unsigned int getButtonId()
Vec3[float] getPosition()
ctypedef void (*HDButtonCallback)(HDButtonEvent, void *)
cdef extern from "Scene.h":
cdef cppclass Scene:
Scene()
void setDrillButtonCallback( HDButtonCallback, void*)
cdef void pyHDButtonCallback(HDButtonEvent e, void *user_data):
print <object>user_data
(<object>user_data)( (e.isPressed(), e.getButtonId(), topy_vec3f(e.getPosition())) )
cdef class pyScene:
cdef Scene * m_scene
def __init__(self):
self.m_scene = new Scene()
def __del__(self):
del self.m_scene
def setDrillButtonCallback(self, func):
print func
self.m_scene.setDrillButtonCallback(pyHDButtonCallback, <void*>func)
以下是我试图称之为:
class RenderCanvas(GLCanvas):
def __init__(self, parent):
self.scene = cybraincase.pyScene()
self.scene.setDrillButtonCallback(self.OnDrillButtonPress)
def OnDrillButtonPress(self, event):
print event
最初运行此代码时,会打印出来:
<bound method RenderCanvas.OnDrillButtonPress of <UI.RenderCanvas; proxy of <Swig Object of type 'wxGLCanvas *' at 0x42b70a8> >>
这似乎是正确的。问题是当触发回调时,会打印出来:
<bound method Shell.readline of <wx.py.shell.Shell; proxy of <Swig Object of type 'wxStyledTextCtrl *' at 0x3a12348> >>
正在调用一个完全不同的绑定方法。但是,当我使OnDrillButtonPress
成为静态方法时,
<function OnDrillButtonPress at 0x042FC570>
在初始化和触发呼叫时都会打印出来。
将保存绑定方法与void *不兼容吗?
答案 0 :(得分:3)
感谢Stefan Behnel和Mark Florisson对cython讨论组的评论,问题是对我的绑定方法的引用超出了范围并且收集了垃圾。
解决方案是这样做:
cdef class pyScene:
cdef Scene * m_scene
cdef object drill_button_func
def setDrillButtonCallback(self, func):
self.m_scene.setDrillButtonCallback(pyHDButtonCallback, <void*>func)
self.drill_button_func = func
通过保持对类中绑定方法的引用,它不会被清除,直到它停止使用。