【问题标题】:Cython callback works correctly for function, but not for bound methodCython 回调适用于函数,但不适用于绑定方法
【发布时间】:2011-09-08 03:08:58
【问题描述】:

我正在为 C++ 库实现基于 cython 的接口。我实现了一个回调系统,它可以与普通函数一起使用,但在传入绑定方法时会奇怪地失败。这是我的 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 

最初运行此代码时,会打印以下内容: &lt;bound method RenderCanvas.OnDrillButtonPress of &lt;UI.RenderCanvas; proxy of &lt;Swig Object of type 'wxGLCanvas *' at 0x42b70a8&gt; &gt;&gt;

这似乎是正确的。问题是当回调被触发时,会打印出来: &lt;bound method Shell.readline of &lt;wx.py.shell.Shell; proxy of &lt;Swig Object of type 'wxStyledTextCtrl *' at 0x3a12348&gt; &gt;&gt;

正在调用一个完全不同的绑定方法。但是,当我将OnDrillButtonPress 设为静态方法时, &lt;function OnDrillButtonPress at 0x042FC570&gt; 在初始化和触发调用时都打印出来。

将绑定方法保存为 void* 是否不兼容?

【问题讨论】:

    标签: python callback cython


    【解决方案1】:

    感谢 Stefan Behnel 和 Mark Florisson 在 cython 讨论组中的 cmets,问题是对我的绑定方法的引用超出了范围并收集了垃圾。

    解决方案是这样做:

    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
    

    通过在类中保留对绑定方法的引用,它在停止使用之前不会被清理。

    【讨论】:

      猜你喜欢
      • 2017-06-19
      • 2016-01-27
      • 1970-01-01
      • 1970-01-01
      • 2021-07-14
      • 1970-01-01
      • 2018-08-23
      • 2011-06-15
      • 1970-01-01
      相关资源
      最近更新 更多