10

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

何が起こっているのかを見つけるために、私はたくさんの印刷ステートメントを入れました。そのうちの1つは、タイプ名と参照カウントをセグメンテーション違反の前の行に出力します。これにより「関数3」が生成されるため、関数はまだ破棄されていないと想定する必要があります。

私はswigに以下を渡します:

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

ここでPyMenuCallbackを作成します

何がセグメンテーション違反を引き起こしているのか途方に暮れています、何かアイデアはありますか?

4

1 に答える 1

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

必ず含めてください

#include "wx/wxPython/wxPython.h"
#include "wx/wxPython/wxPython_int.h"
于 2015-02-18T16:03:41.503 に答える