我正在实现一个基于 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
最初运行此代码时,将打印以下内容:
< >>
看来是对的。问题是当回调被触发时,会打印以下内容:
< >>
正在调用完全不同的绑定方法。但是,当我将 OnDrillButtonPress 设为静态方法时,
<0x042FC570 处的 OnDrillButtonPress 函数>
在初始化和触发调用时都会打印。
将绑定方法保存为 void* 是否不兼容?
I am implementing a cython-based interface to a C++ library. I implemented a callback system that works with normal functions but fails strangely when passing in bound methods. Here is a portion of my cython code:
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)
And here is how I'm trying to call it:
class RenderCanvas(GLCanvas):
def __init__(self, parent):
self.scene = cybraincase.pyScene()
self.scene.setDrillButtonCallback(self.OnDrillButtonPress)
def OnDrillButtonPress(self, event):
print event
When this code is run initially, this is printed:
<bound method RenderCanvas.OnDrillButtonPress of <UI.RenderCanvas; proxy of <Swig Object of type 'wxGLCanvas *' at 0x42b70a8> >>
That seems right. The problem is when the callback is triggered, this is printed:
<bound method Shell.readline of <wx.py.shell.Shell; proxy of <Swig Object of type 'wxStyledTextCtrl *' at 0x3a12348> >>
A totally different bound method is being called. However, when I make OnDrillButtonPress
a static method,
<function OnDrillButtonPress at 0x042FC570>
is printed both on initialization and triggering calls.
Is there an incompatibility with saving bound methods as void*?
发布评论
评论(1)
感谢 Stefan Behnel 和 Mark Florisson 在 cython 讨论组上的评论,问题是对我的绑定方法的引用超出了范围并被垃圾收集。
解决方案是这样做:
通过在类中保留对绑定方法的引用,直到停止使用它才会被清理。
Thanks to comments by Stefan Behnel and Mark Florisson on the cython discussion group, the problem is that the reference to my bound method was going out of scope and getting garbage collected.
The solution was to do this:
By keeping a reference to the bound method in the class, it doesn't get cleaned up until it stops being used.