I have a wx.py.Shell.shell widget which lets the user execute python code that interacts with my program. I want to be able to pass a function that the user defines in this space to my C++ code (Through the wxswig generated wrapper around my custom widget)and execute it.
In my C++ code I'm using a std::function <> class to invoke bound functions (C++ or Python)
So I created a simple class to wrap the PyObject with the function call operator. However I get a segfault when I try to call the 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);
}
In my attempts to find what was going on, I put a bunch of print statements. One of which prints the type name and reference count the line before the segfault. This results in "function 3" so I have to assume the function has not been destroyed yet.
I'm passing the following to swig:
void AddOption (std::string name, PyObject *pycallback);
In which I construct a PyMenuCallback
I'm at a loss for what's causing the segfault, any ideas?