123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- // 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/type_traits.hpp>
- # include <boost/python/detail/none.hpp>
- # include <boost/python/type_id.hpp>
- # include <boost/python/errors.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 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>() \
- { \
- return type_info (typeid (Pointee *)); \
- } \
- template<> \
- inline type_info type_id<const volatile Pointee&>() \
- { \
- return type_info (typeid (Pointee *)); \
- } \
- }}
- # endif // OPAQUE_POINTER_CONVERTER_HPP_
|