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