Passing values from C++ to embedded python.
Mark Rowe
bdash at gmx.net
Thu May 30 01:00:56 EDT 2002
Justin Dubs wrote:
>Hey everyone,
>
>I have a C++ app in which I have embedded the python interpreter. I have a
>thread which does the simple Py_Initialize(), PyRun_InteractiveLoop(),
>Py_Finalize() business using stdin and stdout. Meanwhile the main thread
>does all the regular functionality of the app in another window. I have
>several classes, written in C++, which I have wrapped with SWIG and compiled
>into a shared library. C++ can instantiate the original classes, obviously,
>as they are written in C++. Python can instantiate the wrapped classes from
>the shared library and that also works perfectly.
>
>So, my problem is thus:
>
>If I have a pointer to an instance of one of these classes in C++, how can I
>create a python variable that points to the same instance?
>
>In other words, in pseudocode:
>
>In C++:
> MyClass *foo = new MyClass();
> foo->SetAnswer(42);
> // insert unknown code to communicate foo to python
>
>In Python, from my interactive interpreter running on stdin and stdout
>within the C++ app:
> # insert unknown code to receive foo from c++
> >>> foo.getAnswer();
> 42
>
>I hope you can understand what I am trying to accomplish. I need to make
>python aware of an instance of a variable that exists in C++. I tried doing
>this some simple ways from C++ using PyCObject_* and PyInstance_* and
>PyNew_* and other things. But, alas, I am but a beginner with the Python/C
>API and I could really use some help.
>
>Thanks a lot everyone,
>
>Justin Dubs
>
>
>
>
Hello,
I had a similar problem recently. I'm unsure if the method that I used
to solve it is the simplest way to do so, but so far it has worked for me.
The SWIG function SWIG_NewPointerObj can be used to return a PyObject *
for your wrapped class. If you are using SWIG shadow classes, you then
have to create a wrapper class instance that shadows the newly created
PyObject *. You can then insert the PyObject * into the appropriate
Python namespace.
eg (Edited and untested):
PyObject *ToConsole(Console *c);
// Insert console object to into Python namespace
void InsertObject(Console *m_console)
{
PyObject * console_s = NULL, * a3d_m = NULL, * a3d_md = NULL, *
console_class = NULL;
PyObject * console = NULL, * main = NULL, * main_d = NULL, *
arg_tuple = NULL;
console_s = ToConsole(m_console);
// Create Python shadow class from Python Object
// A3D.py is the shadow class file generated by SWIG
a3d_m = PyImport_ImportModule("A3D");
a3d_md = PyModule_GetDict(a3d_m);
console_class = PyDict_GetItemString(a3d_md, "ConsolePtr");
arg_tuple = PyTuple_New(1);
PyTuple_SetItem(arg_tuple, 0, console_s) ;
console = PyObject_CallObject(console_class, arg_tuple);
Py_XDECREF(arg_tuple);
arg_tuple = NULL;
// Insert Python shadow class into global namespace
main = PyImport_AddModule("__main__");
main_d = PyModule_GetDict(main);
PyDict_SetItemString(main_d, "console", console);
Py_XDECREF(console);
Py_XDECREF(a3d_m);
console = NULL;
a3d_m = NULL;
}
and in your SWIG file, create a small section like the following:
%{
extern swig_type_info _swigt__p_Console[];
PyObject *ToConsole(Console *c)
{
// _swigt__p_Console is a generated structure(?) that represents the
C++ class
extern swig_type_info _swigt__p_Console[];
return SWIG_NewPointerObj(c, _swigt__p_Console, 0);
}
%}
The C++ instance that you pass to InsertObject is then available in
Python as console in the __main__ namespace. I hope that this makes
sense, and helps you :D
Mark
More information about the Python-list
mailing list