簡體   English   中英

來自SWIG PyObject_Call Segfault的Python回調

[英]Python Callback from SWIG PyObject_Call Segfault

我有一個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);
}

在我試圖找到正在發生的事情時,我放了一堆打印語句。 其中一個在segfault之前打印類型名稱和引用計數。 這導致“功能3”,所以我必須假設該功能尚未被破壞。

我將以下內容傳遞給swig:

void AddOption (std::string name, PyObject *pycallback);

我在其中構建了一個PyMenuCallback

我不知道是什么導致了段錯誤,任何想法?

由於調用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);
}

一定要包括

#include "wx/wxPython/wxPython.h"
#include "wx/wxPython/wxPython_int.h"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM