Passing values from C++ to embedded python.

Justin Dubs jtdubs at eos.ncsu.edu
Sun Aug 18 03:40:10 CEST 2002


"Justin Dubs" <jtdubs at eos.ncsu.edu> wrote in message
news:HWzJ8.43861$6v2.1791415 at twister.southeast.rr.com...
> "Mark Rowe" <bdash at gmx.net> wrote in message
> news:mailman.1022734969.31865.python-list at python.org...
> > 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
> >
>
> Thanks a lot Mark,
>
> I have a new problem now though.  :-).  our idea makes sense, I wrote the
> code, I put the stuff in the SWIG interface file, and it compiled
perfectly.
> Woohoo.  However, I can't figure out how to link it now.
>
> Here's what I have, simplified:
>
> classtowrap.cpp            # the class i'm trying to wrap
> classtowrap.h                # it's header file
> classtowrap.i                # swig interface file
> classtowrap_wrap.cxx    # generated c++ wrapper class from SWIG
> classtowrap.py                # python shadow class from SWIG
> classtowrapc.so                # the compiled, shared library from the
> classtowrap.cpp and the classtowrap_wrap.cxx that python can import
>
> main.cpp                        # the main driver program
>
> So, the main.cpp is what gets the python interpreter running and needs to
> send the instance into the python namespace.  It, therefore, needs to use
> that method we defined in our classtowrap.i file, which was put in the
> classtowrap_wrap.cxx file, which is now in the shared library
> classtowrapc.so.
>
> I can't, of course, just do a -lclasstowrapc because libraries need to
start
> with "lib", so I made a link from libclasstowrapc.so -> classtowrapc.so.
> Now I did the compilation of main.cpp with a -lclasstowrapc at the end of
> it.  Here's the error I got:
>
> ld: libclasstowrapc.dylib is input for the dynamic link editor, is not
> relocatable by the static link editor again
>
> Mac OS X was nice enough to copy my symbolic link, this time with a .dylib
> extension, as is the default for dynamically linked libraries on this OS.
> However, being a dynamic library, you can't statically link it.  So, how
DO
> you dynamically link a library?  I've never dealt with this kind of thing
> before.
>
> Thanks again for your help,
>
> Justin Dubs
>
>

Nevermind, that was easy.  dlopen(), dlsym(), dlclose(), dlerror(), -ldl.
No problem.

Thanks again,

Justin





More information about the Python-list mailing list