Mam widżet wx.py.Shell.shell, który pozwala użytkownikowi na wykonanie kodu Pythona, który współdziała z moim programem. Chcę móc przekazać funkcję, którą użytkownik definiuje w tej przestrzeni do mojego kodu C++ (poprzez wxswig wygenerował opakowanie wokół mojego niestandardowego widgetu) i wykonać ją.Python Callback z SWIG PyObject_Call Segfault
W moim kodu C++ używam std :: function <> klasa wywoływać funkcje stopniu (C++ lub Python)
Stworzyłem więc prostą klasę zawinąć PyObject z operatorem wywołania funkcji. Jednak otrzymuję segfault, gdy próbuję wywołać 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);
}
W moich próbach znalezienia tego, co się dzieje, włożyłem kilka wydruków. Jeden z nich wypisuje nazwę typu i odnośnik zlicza linię przed segfault. Wynika z tego "funkcja 3", więc muszę założyć, że funkcja nie została jeszcze zniszczona.
olewam dodaje do haust:
void AddOption (std::string name, PyObject *pycallback);
w którym skonstruować PyMenuCallback
jestem ze stratą dla tego, co jest przyczyną segfault, jakieś pomysły?
myślę, że naruszył zasadę trzech [] (http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three), nie dostarczając 'operator =' dla 'PyMenuCallback'. Nie jestem pewien, czy to problem tutaj, czy nie, ale z pewnością może powodować problemy. – Flexo
Nie udało mi się odtworzyć tego na moim komputerze za pomocą przypadku testowego. Udało mi się potwierdzić, że 'operator =' nie jest używany przez przypadek, ale kod zadziałał i nie wygenerował żadnych ostrzeżeń z valgrindu. Czy możesz rozszerzyć i uprościć swoją teczkę testową nieco, być może, używając '% inline' i'% {%} ', aby stworzyć tylko jeden plik interfejsu? Na przykład. Użyłem: [this] (http://pastebin.com/XYXj3a4p) do przetestowania, które może mieć subtelne różnice w stosunku do tego, co używasz/pakujesz. – Flexo
Rzeczywiście, dobry połów, zapomniałem operatora =. W tej chwili nie jest on jednak wykorzystywany, ale dodam go. – Tocs