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