[C++-sig] Creating an instance of a Python class in C++: PyRun_String?

Dirk Gerrits dirk at gerrits.homeip.net
Thu Nov 14 22:39:05 CET 2002


I have an abstract base class and one concrete derivative in C++ and I 
have wrapped the base class with Boost.Python. Now I want to define 
another derived class, but I want to do this in Python. With the 
Boost.Python wrapper, this is easy. But now comes the hard part: I want 
to create an instance of this Python class and use it in C++.

The first thing I did was searching the latest posts on this mailing 
list which gave me 2 clues:
  - the example at the bottom of: 
  - PyRun_String

Here's what I came up with:

#include <iostream>

// The abstract base class
class Base
     virtual ~Base() {};

     virtual void f() = 0;

// The C++ derived class
class CppDerived : public Base
     virtual ~CppDerived() {}

     void f()
         std::cout << "CppDerived::f()\n";

#include <boost/python.hpp>
#include <boost/python/extract.hpp>
namespace python = boost::python;

     // Boost.Python wrapper for Base
     struct BaseWrap : public Base
         BaseWrap(PyObject* self_)
             : self(self_) {}

         void f() { return python::call_method<void>(self, "f"); }

         PyObject* self;


     python::class_<Base, BaseWrap, boost::noncopyable>("Base", 

int main()
     // Register the wrapper module
     PyImport_AppendInittab("pythontest", initpythontest);

     // Initialize the interpreter

     // Create and use an instance of the C++ derived class
     boost::shared_ptr<Base> cpp(new CppDerived);

     // Define the Python derived class
         "from pythontest import *\n"
         "class PythonDerived(Base):\n"
         "    def __init__(self):\n"
         "        pass\n"
         "    def f(self):\n"
         "        print \"PythonDerived::f()\"\n"

     // Create and use an instance of the Python derived class
     Base& py = python::extract<Base&>(
         PyRun_String("PythonDerived()\n", ???, ???, ???);

     std::cout << "\nPress <enter> to quit...";

     // Release the Python interpreter

I feel like I'm almost there, but I just can't get this to work.

Firstly, I don't know which arguments to feed into PyRun_String. The 
python.org docs didn't really help me that much: I don't have any 
dictionaries of globals and locals, and what exactly is a start token? I 
tried 0s for all 3 arguments and then compiling, but that brought me to 
the second issue:

The 'Base& py = ...' line gave a compilation error saying that a 
python::extract<Base > could not be converted to a Base&. Then I tried 
replacing both Base& with Base*, which compiled but gave an access 

Can anyone help me out?

Thanks in advance,
Dirk Gerrits

More information about the Cplusplus-sig mailing list