// Copyright David Abrahams 2001. Permission to copy, use, // modify, sell and distribute this software is granted provided this // copyright notice appears in all copies. This software is provided // "as is" without express or implied warranty, and with no claim as // to its suitability for any purpose. #include "simple_type.hpp" #include "complicated.hpp" #include #include #include #include #include #include #include #include #include #include #include #include #include #include // Declare some straightforward extension types extern "C" void dealloc(PyObject* self) { PyObject_Del(self); } // Noddy is a type we got from one of the Python sample files struct NoddyObject : PyObject { int x; }; PyTypeObject NoddyType = { PyObject_HEAD_INIT(NULL) 0, "Noddy", sizeof(NoddyObject), 0, dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ }; // Create a Noddy containing 42 PyObject* new_noddy() { NoddyObject* noddy = PyObject_New(NoddyObject, &NoddyType); noddy->x = 42; return (PyObject*)noddy; } // Simple is a wrapper around a struct simple, which just contains a char* struct SimpleObject { PyObject_HEAD simple x; }; struct extract_simple_object { static simple& execute(SimpleObject& o) { return o.x; } }; PyTypeObject SimpleType = { PyObject_HEAD_INIT(NULL) 0, "Simple", sizeof(SimpleObject), 0, dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ }; // Create a Simple containing "hello, world" PyObject* new_simple() { SimpleObject* simple = PyObject_New(SimpleObject, &SimpleType); simple->x.s = "hello, world"; return (PyObject*)simple; } // // Declare some wrappers/unwrappers to test the low-level conversion // mechanism. See boost/python/converter/source.hpp,target.hpp for a // description of how the type parameters to wrapper<> and unwrapper<> // are selected. // using boost::python::converter::from_python_data; using boost::python::to_python_converter; // Wrap a simple by copying it into a Simple struct simple_to_python : to_python_converter { static PyObject* convert(simple const& x) { SimpleObject* p = PyObject_New(SimpleObject, &SimpleType); p->x = x; return (PyObject*)p; } }; int noddy_to_int(PyObject* p, from_python_data&) { return static_cast(p)->x; } // Extract a mutable reference to an int from a Noddy. int& noddy_to_int_ref(PyObject* p, from_python_data&) { return static_cast(p)->x; } // // Some C++ functions to expose to Python // // Returns the length of s's held string int f(simple const& s) { return strlen(s.s); } // A trivial passthru function for simple objects simple const& g(simple const& x) { return x; } struct A { A() : x(0) {} virtual ~A() {} char const* name() { return "A"; } int x; }; struct B : A { B() : x(1) {} char const* name() { return "B"; } int x; }; struct C : A { C() : x(2) {} char const* name() { return "C"; } virtual ~C() {} int x; }; struct D : B, C { D() : x(3) {} char const* name() { return "D"; } int x; }; A take_a(A const& a) { return a; } B take_b(B const& b) { return b; } C take_c(C const& c) { return c; } D take_d(D const& d) { return d; } BOOST_PYTHON_MODULE_INIT(m1) { using boost::python::module; using boost::python::class_; using boost::python::converter::from_python_converter; using boost::python::reference_from_python; using boost::python::value_from_python; using boost::python::type_from_python; using boost::python::get_member; using boost::python::copy_const_reference; using boost::python::return_value_policy; using boost::mpl::type_list; // Create the converters; they are self-registering/unregistering. static simple_to_python c1; static from_python_converter c2( &(boost::python::type_from_python<&NoddyType>::convertible), noddy_to_int); static from_python_converter c3( &(boost::python::type_from_python<&NoddyType>::convertible), noddy_to_int_ref); static boost::python::reference_from_python< &SimpleType , simple , SimpleObject , extract_simple_object > unwrap_simple; module m1("m1"); typedef boost::python::objects::pointer_holder_generator< boost::python::objects::shared_ptr_generator > use_shared_ptr; m1 // Insert the metaclass for all extension classes .setattr("xclass", boost::python::objects::class_metatype()) // Insert the base class for all extension classes .setattr("xinst", boost::python::objects::class_type()) .def("new_noddy", new_noddy) .def("new_simple", new_simple) // Expose f() .def("f", f) // Expose g() .def("g", g , return_value_policy() ) .def("take_a", take_a) .def("take_b", take_b) .def("take_c", take_c) .def("take_d", take_d) .add( class_, use_shared_ptr>("A") .def_init() .def("name", &A::name) ) ; // sequence points don't ensure that "A" is constructed before "B" // or "C" below if we make them part of the same chain m1 .add( class_, use_shared_ptr>("B") .def_init() .def("name", &B::name) ) .add( class_, use_shared_ptr>("C") .def_init() .def("name", &C::name) ) ; m1 .add( class_, use_shared_ptr>("D") .def_init() .def("name", &D::name) ) .add( class_("complicated") .def_init(type_list()) .def_init(type_list()) .def("get_n", &complicated::get_n) ) ; } #include "module_tail.cpp"