Boost logo

Boost Users :

From: Lawrence Spector (Lawrence.Spector_at_[hidden])
Date: 2007-07-09 09:38:41


I created an example of code that demonstrates the error.

Here's what the code looks like, as of right now:

PythonPassReference.cpp:

#include <boost/python.hpp>

#include "TestClass.hpp"

#include "TestClassWrap.hpp"

#include <iostream>

using namespace boost::python;

int main()

{

        try

        {

                Py_Initialize();

                object main_module((

                        handle<>(borrowed(PyImport_AddModule("__main__")))));

                object main_namespace = main_module.attr("__dict__");

                TestClass testClass(std::cout, 3, 9.6f, 'Q');

                {

                        handle<> ignored((PyRun_String(

                                "import PythonInterface"

                          , Py_file_input

                          , main_namespace.ptr()

                          , main_namespace.ptr())

                        ));

                }

                TestClassWrap testClassWrapper(testClass);

                boost::python::object pyTestClass(testClassWrapper);

// Works: pyTestClass.attr("output")();

                {

                        handle<> ignored((PyRun_String(

// Works: "pyTestClass = PythonInterface.TestClass(6, 8.3, 'W')\n"

                                "pyTestClass.output()\n" // Error unless the previous line is uncommented

                          , Py_file_input

                          , main_namespace.ptr()

                          , main_namespace.ptr())

                        ));

                }

        }

        catch(boost::python::error_already_set& e)

        {

                std::cerr << "Caught error_already_set" << std::endl;

                if (PyErr_Occurred() != 0)

                {

                        PyErr_Print();

                } // end if

        }

        catch(...)

        {

                std::cerr << "Caught unknown error" << std::endl;

        } // end try-catch

        std::cin.get();

        return 0;

} // end main

TestClass.hpp:

#pragma once

#include <iostream>

class TestClass

{

private:

        std::ostream& m_outStream;

        int m_x;

        float m_y;

        char m_z;

public:

        TestClass(std::ostream& p_outStream, int p_x, float p_y, char p_z) :

                m_outStream(p_outStream), m_x(p_x), m_y(p_y), m_z(p_z)

        {

        } // end TestClass

        ~TestClass()

        {

        } // end TestClass

        void output()

        {

                m_outStream << "x = " << m_x << ", y = " << m_y << ", z = " << m_z << "\n";

        } // end callMethod

}; // end TestClass

TestClassWrap.hpp:

#pragma once

#include "TestClass.hpp"

class TestClassWrap

{

private:

        TestClass m_testClass;

public:

        TestClassWrap(const TestClass& p_testClass) :

                m_testClass(p_testClass)

        {

        } // end TestClassWrap

        TestClassWrap(int p_x, float p_y, char p_z) :

                m_testClass(std::cout, p_x, p_y, p_z)

        {

        } // end TestClass

        ~TestClassWrap()

        {

        } // end TestClass

        void output()

        {

                m_testClass.output();

        } // end callMethod

}; // end TestClassWrap

PythonInterface.cpp (Built with BJam, makes PythonInterface.pyd, PythonInterface.lib):

#include <string>

#include <boost/python.hpp>

#include <iostream>

#include "TestClass.hpp"

#include "TestClassWrap.hpp"

using namespace boost::python;

BOOST_PYTHON_MODULE(PythonInterface)

{

        class_<TestClassWrap>("TestClass", init<int, float, char>())

                .def("output", &TestClassWrap::output)

                ;

} // end module

As you can see in the example above, I have an object which I wrap and then pass to python as follows:

TestClassWrap testClassWrapper(testClass); boost::python::object pyTestClass(testClassWrapper);

This works just fine, and I can call methods on the object. However, when I try to run it as a string (as it would be if read from a .py script file), I get an error. Here's the code for that:

                {

                        handle<> ignored((PyRun_String(

                                "pyTestClass.output()\n" // Error unless the previous line is uncommented

                          , Py_file_input

                          , main_namespace.ptr()

                          , main_namespace.ptr())

                        ));

                }

Which produces the following error (based on my catching and outputting the error):

Caught error_already_set

Traceback (most recent call last):

  File "<string>", line 1, in <module>

NameError: name 'pyTestClass' is not defined

So, I guess the question is, how do I expose an instance called pyTestClass, in such a way, that I can call methods on it from a script? Or is there some mistake I'm making, that's preventing this from fully working?

Thanks in advance,

Lawrence



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net