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