从SWIG PyObject_Call Segfau调用Python回调

2024-10-04 03:25:35 发布

您现在位置:Python中文网/ 问答频道 /正文

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

我在C++代码中使用了STD::Lo.&Gt类来调用绑定函数(C++或Python)

所以我创建了一个简单的类,用函数调用操作符包装PyObject。但是,当我试图调用PyObject*时,会出现一个segfault。在

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);
}

在我试图找出到底发生了什么的时候,我放了一堆打印声明。 其中一个在segfault之前的行打印类型名和引用计数。这就产生了“函数3”,所以我必须假设这个函数还没有被破坏。在

我把下面的东西交给斯威格:

^{pr2}$

我在里面建造了一个侏儒怪

我不知道是什么原因造成的,有什么想法吗?在


Tags: 函数代码pyidifcheckcallbackpyobject
1条回答
网友
1楼 · 发布于 2024-10-04 03:25:35

因为C++调用Python回调是在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);
}

确保包括

^{pr2}$

相关问题 更多 >