Chris@16: // Copyright Gottfried Ganßauge 2003..2006. Chris@16: // Distributed under the Boost Software License, Version 1.0. (See Chris@16: // accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: /* Chris@16: * Generic Conversion of opaque C++-pointers to a Python-Wrapper. Chris@16: */ Chris@16: # ifndef OPAQUE_POINTER_CONVERTER_HPP_ Chris@16: # define OPAQUE_POINTER_CONVERTER_HPP_ Chris@16: Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: Chris@16: # include Chris@16: Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: Chris@16: // opaque -- Chris@16: // Chris@16: // registers to- and from- python conversions for a type Pointee. Chris@16: // Chris@16: // Note: Chris@16: // In addition you need to define specializations for type_id Chris@16: // on the type pointed to by Pointer using Chris@16: // BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee) Chris@16: // Chris@16: // For an example see libs/python/test/opaque.cpp Chris@16: // Chris@16: namespace boost { namespace python { Chris@16: Chris@16: template Chris@16: struct opaque Chris@16: { Chris@16: opaque() Chris@16: { Chris@16: if (type_object.tp_name == 0) Chris@16: { Chris@16: type_object.tp_name = const_cast(type_id().name()); Chris@16: if (PyType_Ready (&type_object) < 0) Chris@16: { Chris@16: throw error_already_set(); Chris@16: } Chris@16: Chris@16: this->register_self(); Chris@16: } Chris@16: } Chris@16: Chris@16: static opaque instance; Chris@16: private: Chris@16: Chris@16: static void* extract(PyObject* op) Chris@16: { Chris@16: return PyObject_TypeCheck(op, &type_object) Chris@16: ? static_cast(implicit_cast(op))->x Chris@16: : 0 Chris@16: ; Chris@16: } Chris@16: Chris@16: static PyObject* wrap(void const* px) Chris@16: { Chris@16: Pointee* x = *static_cast(px); Chris@16: Chris@16: if (x == 0) Chris@16: return detail::none(); Chris@16: Chris@16: if ( python_instance *o = PyObject_New(python_instance, &type_object) ) Chris@16: { Chris@16: o->x = x; Chris@16: return static_cast(implicit_cast(o)); Chris@16: } Chris@16: else Chris@16: { Chris@16: throw error_already_set(); Chris@16: } Chris@16: } Chris@16: Chris@16: void register_self() Chris@16: { Chris@16: converter::registration const *existing = Chris@16: converter::registry::query (type_id()); Chris@16: Chris@16: if ((existing == 0) || (existing->m_to_python == 0)) Chris@16: { Chris@16: #ifndef BOOST_PYTHON_NO_PY_SIGNATURES Chris@16: converter::registry::insert(&extract, type_id(), &get_pytype); Chris@16: converter::registry::insert(&wrap, type_id(), &get_pytype); Chris@16: #else Chris@16: converter::registry::insert(&extract, type_id()); Chris@16: converter::registry::insert(&wrap, type_id()); Chris@16: #endif Chris@16: } Chris@16: } Chris@16: Chris@16: struct python_instance Chris@16: { Chris@16: PyObject_HEAD Chris@16: Pointee* x; Chris@16: }; Chris@16: Chris@16: static PyTypeObject type_object; Chris@16: #ifndef BOOST_PYTHON_NO_PY_SIGNATURES Chris@16: static PyTypeObject const *get_pytype(){return &type_object; } Chris@16: #endif Chris@16: }; Chris@16: Chris@16: template Chris@16: opaque opaque::instance; Chris@16: Chris@16: template Chris@16: PyTypeObject opaque::type_object = Chris@16: { Chris@16: PyVarObject_HEAD_INIT(NULL, 0) Chris@16: 0, Chris@16: sizeof( BOOST_DEDUCED_TYPENAME opaque::python_instance ), Chris@16: 0, Chris@16: ::boost::python::detail::dealloc, Chris@16: 0, /* tp_print */ Chris@16: 0, /* tp_getattr */ Chris@16: 0, /* tp_setattr */ Chris@16: 0, /* tp_compare */ Chris@16: 0, /* tp_repr */ Chris@16: 0, /* tp_as_number */ Chris@16: 0, /* tp_as_sequence */ Chris@16: 0, /* tp_as_mapping */ Chris@16: 0, /* tp_hash */ Chris@16: 0, /* tp_call */ Chris@16: 0, /* tp_str */ Chris@16: 0, /* tp_getattro */ Chris@16: 0, /* tp_setattro */ Chris@16: 0, /* tp_as_buffer */ Chris@16: 0, /* tp_flags */ Chris@16: 0, /* tp_doc */ Chris@16: 0, /* tp_traverse */ Chris@16: 0, /* tp_clear */ Chris@16: 0, /* tp_richcompare */ Chris@16: 0, /* tp_weaklistoffset */ Chris@16: 0, /* tp_iter */ Chris@16: 0, /* tp_iternext */ Chris@16: 0, /* tp_methods */ Chris@16: 0, /* tp_members */ Chris@16: 0, /* tp_getset */ Chris@16: 0, /* tp_base */ Chris@16: 0, /* tp_dict */ Chris@16: 0, /* tp_descr_get */ Chris@16: 0, /* tp_descr_set */ Chris@16: 0, /* tp_dictoffset */ Chris@16: 0, /* tp_init */ Chris@16: 0, /* tp_alloc */ Chris@16: 0, /* tp_new */ Chris@16: 0, /* tp_free */ Chris@16: 0, /* tp_is_gc */ Chris@16: 0, /* tp_bases */ Chris@16: 0, /* tp_mro */ Chris@16: 0, /* tp_cache */ Chris@16: 0, /* tp_subclasses */ Chris@16: 0, /* tp_weaklist */ Chris@16: #if PYTHON_API_VERSION >= 1012 Chris@16: 0 /* tp_del */ Chris@16: #endif Chris@16: }; Chris@16: }} // namespace boost::python Chris@16: Chris@16: # if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) Chris@16: Chris@16: # define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee) Chris@16: Chris@16: # else Chris@16: Chris@16: // If you change the below, don't forget to alter the end of type_id.hpp Chris@16: # define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee) \ Chris@16: namespace boost { namespace python { \ Chris@16: template<> \ Chris@16: inline type_info type_id(BOOST_PYTHON_EXPLICIT_TT_DEF(Pointee)) \ Chris@16: { \ Chris@16: return type_info (typeid (Pointee *)); \ Chris@16: } \ Chris@16: template<> \ Chris@16: inline type_info type_id( \ Chris@16: BOOST_PYTHON_EXPLICIT_TT_DEF(const volatile Pointee&)) \ Chris@16: { \ Chris@16: return type_info (typeid (Pointee *)); \ Chris@16: } \ Chris@16: }} Chris@16: Chris@16: # endif Chris@16: Chris@16: # endif // OPAQUE_POINTER_CONVERTER_HPP_