[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
Hi.
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:
http://www.boost.org/libs/python/doc/v2/extract.html
- PyRun_String
Here's what I came up with:
#include <iostream>
// The abstract base class
class Base
{
public:
virtual ~Base() {};
virtual void f() = 0;
};
// The C++ derived class
class CppDerived : public Base
{
public:
virtual ~CppDerived() {}
void f()
{
std::cout << "CppDerived::f()\n";
}
};
//-------------------------------------------------------//
#include <boost/python.hpp>
#include <boost/python/extract.hpp>
namespace python = boost::python;
namespace
{
// 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;
};
}
BOOST_PYTHON_MODULE(pythontest)
{
python::class_<Base, BaseWrap, boost::noncopyable>("Base",
python::no_init)
;
}
//-------------------------------------------------------//
int main()
{
// Register the wrapper module
PyImport_AppendInittab("pythontest", initpythontest);
// Initialize the interpreter
Py_Initialize();
// Create and use an instance of the C++ derived class
boost::shared_ptr<Base> cpp(new CppDerived);
cpp->f();
// Define the Python derived class
PyRun_SimpleString(
"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", ???, ???, ???);
py.f();
std::cout << "\nPress <enter> to quit...";
std::cin.get();
// Release the Python interpreter
Py_Finalize();
}
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
violation.
Can anyone help me out?
Thanks in advance,
Dirk Gerrits
More information about the Cplusplus-sig
mailing list