Cython回调对于函数正确工作,但对于绑定方法不正确 [英] Cython callback works correctly for function, but not for bound method

查看:256
本文介绍了Cython回调对于函数正确工作,但对于绑定方法不正确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在实现一个基于cython的接口到C ++库。我实现了一个回调系统,它与正常的函数,但在传递绑定的方法时失败奇怪。这里是我的cython代码的一部分:

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)

调用它:

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;代理< Swig在0x42b70a8处类型为wxGLCanvas *的对象> >>

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> >>

看起来不错。问题是当回调被触发,打印:
< bound方法Shell.readline< wx.py.shell.Shell;代理< Swig对象的类型'wxStyledTextCtrl *'在0x3a12348> >>

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> >>

正在调用完全不同的绑定方法。然而,当我使 OnDrillButtonPress 一个静态方法,
< function OnDrillButtonPress at 0x042FC570>
在初始化和触发调用时都打印。

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.

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

Is there an incompatibility with saving bound methods as void*?

推荐答案

由于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.

解决方法是:

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

通过保留对类中绑定方法的引用,它不会被清除,直到它停止使用。

By keeping a reference to the bound method in the class, it doesn't get cleaned up until it stops being used.

这篇关于Cython回调对于函数正确工作,但对于绑定方法不正确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆