Обратный вызов Cython работает правильно для функции, но не для связанного метода - PullRequest
8 голосов
/ 07 сентября 2011

Я реализую основанный на 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 *?

1 Ответ

3 голосов
/ 07 сентября 2011

Благодаря комментариям Стефана Бехнела и Марка Флориссона в дискуссионной группе по 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

Сохраняя ссылку на связанный метод в классе, он не очищается до тех пор, пока не перестанет использоваться.

...