// Copyright Gottfried Ganßauge 2003. // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) /* * Generic Conversion of opaque C++-pointers to a Python-Wrapper. */ # ifndef OPAQUE_POINTER_CONVERTER_HPP_ # define OPAQUE_POINTER_CONVERTER_HPP_ # include # include # include # include # include # include # include // opaque_pointer_converter -- // // usage: opaque_pointer_converter("name") // // registers to- and from- python conversions for a type Pointer, // and a corresponding Python type called "name". // // Note: // In addition you need to define specializations for type_id // on the type pointed to by Pointer using // BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee) // // For an example see libs/python/test/opaque.cpp // namespace boost { namespace python { namespace detail { template struct opaque_pointer_converter_requires_a_pointer_type # if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__) {} # endif ; } template struct opaque_pointer_converter : to_python_converter< Pointer, opaque_pointer_converter > { BOOST_STATIC_CONSTANT( bool, ok = is_pointer::value); typedef typename mpl::if_c< ok , Pointer , detail::opaque_pointer_converter_requires_a_pointer_type >::type ptr_type; private: struct instance; public: explicit opaque_pointer_converter(char const* name) { type_object.tp_name = const_cast (name); lvalue_from_pytype< opaque_pointer_converter, &opaque_pointer_converter::type_object >(); } static PyObject* convert(ptr_type x) { PyObject *result = 0; if (x != 0) { instance *o = PyObject_New (instance, &type_object); o->x = x; result = &o->base_; } else { result = detail::none(); } return (result); } static typename ::boost::remove_pointer::type& execute(instance &p_) { return *p_.x; } private: static PyTypeObject type_object; // This is a POD so we can use PyObject_Del on it, for example. struct instance { PyObject base_; ptr_type x; }; }; template PyTypeObject opaque_pointer_converter::type_object = { PyObject_HEAD_INIT(NULL) 0, 0, sizeof(typename opaque_pointer_converter::instance), 0, ::boost::python::detail::dealloc }; }} // namespace boost::python # ifdef BOOST_MSVC // MSC works without this workaround, but needs another one ... # define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee) \ BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(Pointee) # else # define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee) \ namespace boost { namespace python { \ template<> \ inline type_info type_id(BOOST_PYTHON_EXPLICIT_TT_DEF(Pointee)) \ { \ return type_info (typeid (Pointee *)); \ } \ template<> \ inline type_info type_id( \ BOOST_PYTHON_EXPLICIT_TT_DEF(const volatile Pointee&)) \ { \ return type_info (typeid (Pointee *)); \ } \ }} # endif # endif // OPAQUE_POINTER_CONVERTER_HPP_