[Boost.Python] Issues When Object Created in C++ and Then Used From Python

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

on Mon Jul 09 2007, Lawrence Spector <Lawrence.Spector-AT-CanfieldSci.com> wrote:
I created an example of code that demonstrates the error.
Lawrence, I suggest: 1. You post your question to the C++-sig (http://boost.org/more/mailing_lists.htm#cplussig) 2. You include your code as an inline attachment, so that it doesn't come out with an extra blank line betwen every real line of code and wrap around in surprising ways:
Here's what the code looks like, as of right now:
PythonPassReference.cpp:
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())
));
-- Dave Abrahams Boost Consulting http://www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com
participants (2)
-
David Abrahams
-
Lawrence Spector