summaryrefslogtreecommitdiff
path: root/boost/python/opaque_pointer_converter.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/python/opaque_pointer_converter.hpp')
-rw-r--r--boost/python/opaque_pointer_converter.hpp199
1 files changed, 199 insertions, 0 deletions
diff --git a/boost/python/opaque_pointer_converter.hpp b/boost/python/opaque_pointer_converter.hpp
new file mode 100644
index 0000000000..10eb4234c8
--- /dev/null
+++ b/boost/python/opaque_pointer_converter.hpp
@@ -0,0 +1,199 @@
+// Copyright Gottfried Ganßauge 2003..2006.
+// 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 <boost/python/detail/prefix.hpp>
+# include <boost/python/lvalue_from_pytype.hpp>
+# include <boost/python/to_python_converter.hpp>
+# include <boost/python/converter/registrations.hpp>
+# include <boost/python/detail/dealloc.hpp>
+# include <boost/python/detail/none.hpp>
+# include <boost/python/type_id.hpp>
+# include <boost/python/errors.hpp>
+
+# include <boost/type_traits/remove_pointer.hpp>
+# include <boost/type_traits/is_pointer.hpp>
+# include <boost/type_traits/is_void.hpp>
+
+# include <boost/implicit_cast.hpp>
+
+# include <boost/mpl/eval_if.hpp>
+# include <boost/mpl/identity.hpp>
+# include <boost/mpl/assert.hpp>
+
+// opaque --
+//
+// registers to- and from- python conversions for a type Pointee.
+//
+// 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 {
+
+template <class Pointee>
+struct opaque
+{
+ opaque()
+ {
+ if (type_object.tp_name == 0)
+ {
+ type_object.tp_name = const_cast<char*>(type_id<Pointee*>().name());
+ if (PyType_Ready (&type_object) < 0)
+ {
+ throw error_already_set();
+ }
+
+ this->register_self();
+ }
+ }
+
+ static opaque instance;
+private:
+
+ static void* extract(PyObject* op)
+ {
+ return PyObject_TypeCheck(op, &type_object)
+ ? static_cast<python_instance*>(implicit_cast<void*>(op))->x
+ : 0
+ ;
+ }
+
+ static PyObject* wrap(void const* px)
+ {
+ Pointee* x = *static_cast<Pointee*const*>(px);
+
+ if (x == 0)
+ return detail::none();
+
+ if ( python_instance *o = PyObject_New(python_instance, &type_object) )
+ {
+ o->x = x;
+ return static_cast<PyObject*>(implicit_cast<void*>(o));
+ }
+ else
+ {
+ throw error_already_set();
+ }
+ }
+
+ void register_self()
+ {
+ converter::registration const *existing =
+ converter::registry::query (type_id<Pointee*>());
+
+ if ((existing == 0) || (existing->m_to_python == 0))
+ {
+#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
+ converter::registry::insert(&extract, type_id<Pointee>(), &get_pytype);
+ converter::registry::insert(&wrap, type_id<Pointee*>(), &get_pytype);
+#else
+ converter::registry::insert(&extract, type_id<Pointee>());
+ converter::registry::insert(&wrap, type_id<Pointee*>());
+#endif
+ }
+ }
+
+ struct python_instance
+ {
+ PyObject_HEAD
+ Pointee* x;
+ };
+
+ static PyTypeObject type_object;
+#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
+ static PyTypeObject const *get_pytype(){return &type_object; }
+#endif
+};
+
+template <class Pointee>
+opaque<Pointee> opaque<Pointee>::instance;
+
+template <class Pointee>
+PyTypeObject opaque<Pointee>::type_object =
+{
+ PyVarObject_HEAD_INIT(NULL, 0)
+ 0,
+ sizeof( BOOST_DEDUCED_TYPENAME opaque<Pointee>::python_instance ),
+ 0,
+ ::boost::python::detail::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 */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ 0, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+ 0, /* tp_bases */
+ 0, /* tp_mro */
+ 0, /* tp_cache */
+ 0, /* tp_subclasses */
+ 0, /* tp_weaklist */
+#if PYTHON_API_VERSION >= 1012
+ 0 /* tp_del */
+#endif
+};
+}} // namespace boost::python
+
+# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
+
+# define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee)
+
+# else
+
+// If you change the below, don't forget to alter the end of type_id.hpp
+# define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee) \
+ namespace boost { namespace python { \
+ template<> \
+ inline type_info type_id<Pointee>(BOOST_PYTHON_EXPLICIT_TT_DEF(Pointee)) \
+ { \
+ return type_info (typeid (Pointee *)); \
+ } \
+ template<> \
+ inline type_info type_id<const volatile Pointee&>( \
+ BOOST_PYTHON_EXPLICIT_TT_DEF(const volatile Pointee&)) \
+ { \
+ return type_info (typeid (Pointee *)); \
+ } \
+ }}
+
+# endif
+
+# endif // OPAQUE_POINTER_CONVERTER_HPP_