// 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_ |