来自SWIG PyObject_Call Segfault的Python回调

Toc*_*ocs 9 c++ python swig wxpython python-c-api

我有一个wx.py.Shell.shell小部件,它允许用户执行与我的程序交互的python代码.我希望能够将用户在此空间中定义的函数传递给我的C++代码(通过wxswig生成的自定义小部件包装器)并执行它.

在我的C++代码中,我使用std :: function <>类来调用绑定函数(C++或Python)

所以我创建了一个简单的类来用函数调用操作符包装PyObject.但是当我尝试调用PyObject*时,我得到了一个段错误.

class PyMenuCallback
{
    PyObject *Func;
public:
    PyMenuCallback(const PyMenuCallback &op2);
    PyMenuCallback(PyObject *func);
    ~PyMenuCallback ();

    void operator() (int id);
};
/////////////////////////////////////////////////////////
PyMenuCallback::PyMenuCallback(PyObject *func)
    : Func(func)
{
    Py_XINCREF (Func);
    if(!PyCallable_Check(Func))
        cout << "Not a Callable Callback." << endl; //Throw an exception or something
}

PyMenuCallback::PyMenuCallback(const PyMenuCallback &op2)
    : Func (op2.Func)
{
    Py_XINCREF (Func);
    if(!PyCallable_Check(Func))
        cout << "Not a Callable Callback." << endl;
}

PyMenuCallback::~PyMenuCallback()
{
    Py_XDECREF (Func);
}

void PyMenuCallback::operator() (int id)
{
    cout << "Calling Callback" << endl;
    if (Func == 0 || Func == Py_None || !PyCallable_Check(Func))
        return;
    cout << "Building Args" << endl;   
    PyObject *arglist = Py_BuildValue ("(i)",id);
    cout << "Func: " << Func->ob_type->tp_name << " " << Func->ob_refcnt << endl;
    PyObject *result = PyObject_Call(Func,arglist,0); //<<<<<---SEGFAULTS HERE
    cout << "Executed" << endl;
    Py_DECREF(arglist);
    Py_XDECREF(result);
}
Run Code Online (Sandbox Code Playgroud)

在我试图找到正在发生的事情时,我放了一堆打印语句.其中一个在segfault之前打印类型名称和引用计数.这导致"功能3",所以我必须假设该功能尚未被破坏.

我将以下内容传递给swig:

void AddOption (std::string name, PyObject *pycallback);
Run Code Online (Sandbox Code Playgroud)

我在其中构建了一个PyMenuCallback

我不知道是什么导致了段错误,任何想法?

Toc*_*ocs 4

由于调用 python 回调的 C++ 是在 wxWidget 内,并且 swig 包装器是由特殊的 wxPython swig(wxswig?)生成的,因此函数调用周围需要一些线程保护...

固定运算符应该如下所示

void PyMenuCallback::operator() (int id)
{
    cout << "Calling Callback" << endl;
    if (Func == 0 || Func == Py_None || !PyCallable_Check(Func))
        return;
    cout << "Building Args" << endl;   
    PyObject *arglist = Py_BuildValue ("(i)",id);
    cout << "Built: " << arglist << endl;
    cout << "Func: " << Func->ob_type->tp_name << " " << Func->ob_refcnt << endl;

    wxPyBlock_t blocked = wxPyBeginBlockThreads(); //Anti-WxSwig 

    PyObject *result = PyObject_Call(Func,arglist,0);

    wxPyEndBlockThreads(blocked);


    cout << "Executed" << endl;
    Py_XDECREF(arglist);
    Py_XDECREF(result);
}
Run Code Online (Sandbox Code Playgroud)

确保包括

#include "wx/wxPython/wxPython.h"
#include "wx/wxPython/wxPython_int.h"
Run Code Online (Sandbox Code Playgroud)