[C++-sig] Can't get Boost.Python to use extensions generated and wrapped with Py++
Lawrence Spector
Lawrence.Spector at CanfieldSci.com
Tue Jul 17 16:34:36 CEST 2007
Ok, I've been playing with it some more, still not getting everything to work though. I tried the things you said; it still wasn't working. I took out the constructors from the python interface and added shared_ptr support. I then pass the shared_ptr through. It still doesn't work upon creating the object -- it throws an exception, saying that there's no converter.
TestClass:
#pragma once
#include <iostream>
#include <tchar.h>
class TestClass
{
private:
std::ostream& m_outStream;
int m_x;
float m_y;
char m_z;
public:
TestClass() : m_outStream(std::cout), m_x(0), m_y(0), m_z(0) {}
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)
{
std::cout << __FUNCTION__ << " called. this = " << this << std::endl;
} // end TestClass
~TestClass()
{
std::cout << __FUNCTION__ << " called. this = " << this << std::endl;
} // end TestClass
virtual void output()
{
m_outStream << "x = " << m_x << ", y = " << m_y << ", z = " << m_z << "\n";
std::cout << __FUNCTION__ << " called. this = " << this << std::endl;
} // end callMethod
}; // end TestClass
The wrapper:
struct TestClass_wrapper : TestClass, bp::wrapper< TestClass > {
TestClass_wrapper( )
: TestClass( )
, bp::wrapper< TestClass >(){
// null constructor
}
TestClass_wrapper(int p_x, float p_y, char p_z )
: TestClass( boost::ref(std::cout), p_x, p_y, p_z )
, bp::wrapper< TestClass >(){
// constructor
}
virtual void output( ) {
if( bp::override func_output = this->get_override( "output" ) )
func_output( );
else
this->TestClass::output( );
}
void default_output( ) {
TestClass::output( );
}
};
The Boost.Build Python extension code:
#include <string>
#include <boost/python.hpp>
#include <iostream>
#include "TestClass.hpp"
#include "TestClassWrap.hpp"
namespace bp = boost::python;
BOOST_PYTHON_MODULE(PythonInterface){
bp::class_< TestClass_wrapper, boost::shared_ptr<TestClass>, boost::noncopyable >( "TestClass" )
// .def( bp::init< >() )
// .def( bp::init< int, float, char >(( bp::arg("p_x"), bp::arg("p_y"), bp::arg("p_z") )) )
.def(
"output"
, &::TestClass::output
, &TestClass_wrapper::default_output );
}
#include <boost/python.hpp>
#include "TestClass.hpp"
#include "TestClassWrap.hpp"
#include <iostream>
using namespace boost::python;
class Deleter
{
public:
template <class T>
void operator()(T&)
{
}
};
int main()
{
try
{
Py_Initialize();
object main_module((
handle<>(borrowed(PyImport_AddModule("__main__")))));
object main_namespace = main_module.attr("__dict__");
{
handle<> ignored((PyRun_String(
"import PythonInterface\n"
"print dir(PythonInterface)\n"
"print 'HELLO'\n"
, Py_file_input
, main_namespace.ptr()
, main_namespace.ptr())
));
}
TestClass testClass(std::cout, 3, 9.6f, 'Q');
boost::shared_ptr<TestClass> pTestClass(&testClass, Deleter());
boost::python::object pyTestClass(pTestClass);
main_namespace[L"pyTestClass"] = pyTestClass;
std::cout << "### Calling pyTestClass.attr(\"output\")()" << std::endl;
pyTestClass.attr("output")();
std::cout << "### Calling exec(\"pyTestClass.output()\")" << std::endl;
{
object result = exec(
// Works: "pyTestClass = PythonInterface.TestClass(6, 8.3, 'W')\n"
"pyTestClass.output()\n",
main_namespace, main_namespace);
}
std::cout << "### Calling testClassWrapper.output()" << std::endl;
// testClassWrapper.output();
std::cout << "### Calling testClass.output()" << std::endl;
testClass.output();
}
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
Output:
['TestClass', '__doc__', '__file__', '__name__']
HELLO
TestClass::TestClass called. this = 0012FF1C
TestClass::~TestClass called. this = 0012FF1C
Caught error_already_set
TypeError: No to_python (by-value) converter found for C++ type: class boost::shared_ptr<class TestClass>
This is very frustrating. All I want to do is be able to expose classes, create some instances in C++ and use the instances in both C++ and Python. In addition, I want to create some instances in Python, and use those instances from Python and C++. It seems like the wrappers pose a huge problem; I just can't seem to get things working reliably when there's a wrapper involved. I also haven't found enough documentation on the Boost.Python system available in order to get started and be able to actually make use of the system. Any help you can provide would be greatly appreciated.
Thanks,
Lawrence
-----Original Message-----
From: c++-sig-bounces at python.org [mailto:c++-sig-bounces at python.org] On Behalf Of Roman Yakovenko
Sent: Tuesday, July 17, 2007 1:23 AM
To: Development of Python/C++ integration
Subject: Re: [C++-sig] Can't get Boost.Python to use extensions generated and wrapped with Py++
On 7/17/07, Lawrence Spector <Lawrence.Spector at canfieldsci.com> wrote:
> Any ideas what steps I've missed? I've successfully built a few python
> extensions without using Boost.Python, but never successfully using a
> wrapper. Am I missing something?
>
You didn't expose std::ostream class. So, when Boost.Python tries to
create an instance of your class in Python, it sees some argument type
it cannot treat. As a result, you've got an exception.
If you intend to create all your class instance in C++ than you can
exclude constructors.
In this case may be you can pass your object by reference, I am not
sure whether this will work:
TestClass testClass(std::cout, 3, 9.6f, 'Q');
boost::python::object pyTestClass(boost::ref( testClass) );
--
Roman Yakovenko
C++ Python language binding
http://www.language-binding.net/
_______________________________________________
C++-sig mailing list
C++-sig at python.org
http://mail.python.org/mailman/listinfo/c++-sig
More information about the Cplusplus-sig
mailing list