[C++-sig] Make C++-created object accessible by embeded Python Script

dique chezdique at yahoo.com
Mon Oct 27 10:02:14 CET 2003


Hi all,

I have several C++ objects (created with C++ code) and
I want them to be accessible and manipulatable by an
embeded python script. So far I only manage to let the
embeded script access a _copy_ of the C++ object.
Hence whatever changes done to the C++ object in the
python script wouldn't have any effect on the C++
object running in C++ code. How do I make the embeded
script able to access and manipulate the C++ object
directly?

I hope the code below would demonstrate what I mean.

#include <string>
#include <iostream>
#include <boost/python.hpp>

using namespace boost::python;

BOOST_PYTHON_MODULE(_pyembed)
{
    // To define useful functions.
}

class PythonScript
{
public:
    PythonScript()
    {
        PyImport_AppendInittab("_pyembed",
init_pyembed);
        Py_Initialize();
        handle<> mainModule(borrowed(
PyImport_AddModule("__main__") ));
        mainNamespace_ = dict(handle<>(borrowed(
PyModule_GetDict(mainModule.get()))));
    }
    
    virtual ~PythonScript()
    {
        Py_Finalize();
    }

    //! Add a named object which will be accessible by
the script.
    virtual void addNamedObject(const std::string&
name, object& obj)
    {
        dict_[name] = obj;
    }
    
    //! Run the script.
    virtual void run(const std::string& script)
    {
        mainNamespace_.update(dict_);
        try
        {
            object result(handle<>(
PyRun_String(script.c_str(), Py_file_input,
                            mainNamespace_.ptr(),
mainNamespace_.ptr()) ));
        }
        catch(error_already_set)
        {
            PyErr_Print();
        }
    }

private:
    dict dict_;
    dict mainNamespace_;

};

class Test
{
public:
    Test(int i) : i_(i) {}
    int add(int j)
    {
        return i_ += j;
    }
private:
    int i_;
};

class Test2
{
public:
    Test2(int i) : i_(i) {}
    int add(int j)
    {
        return i_ += j;
    }
private:
    int i_;
};

int main(int argc, char* argv[])
{
    PythonScript pythonScript;
    
    // This works nicely. But only limited to objects
created by Python.
    object testClass = class_<Test>("Test",
init<int>())
        .def("add", &Test::add);
    object testObject = testClass(10);
    pythonScript.addNamedObject("test", testObject);
    Test& test = extract<Test&>(testObject)();
    std::cout << "C++: " << test.add(10) << std::endl;
    pythonScript.run("print 'Python:',
test.add(10)\n");
    std::cout << "C++: " << test.add(10) << std::endl;

    // Below doesn't work as expected,
    // as Python and C++ maintain separate copies of
test1.
    Test test1(10);
    object testObject1(test1);
    pythonScript.addNamedObject("test1", testObject1);
    std::cout << "C++: " << test1.add(10) <<
std::endl;
    pythonScript.run("print 'Python:',
test1.add(10)\n");
    std::cout << "C++: " << test1.add(10) <<
std::endl;

    // Another attempt which failed too.
    try
    {
        Test2 test2(10);
        object testClass2 = class_<Test2,
boost::noncopyable>("Test2", init<int>())
            .def("add", &Test2::add);
        object testObject2(test2);
        pythonScript.addNamedObject("test2",
testObject2);
        std::cout << "C++: " << test2.add(10) <<
std::endl;
        pythonScript.run("print 'Python:',
test2.add(10)\n");
        std::cout << "C++: " << test2.add(10) <<
std::endl;
    }
    catch(error_already_set)
    {
        PyErr_Print();
    }
    
    return 0;
}

Thanks,
Dique C.

__________________________________
Do you Yahoo!?
Exclusive Video Premiere - Britney Spears
http://launch.yahoo.com/promos/britneyspears/




More information about the Cplusplus-sig mailing list