1313# include < boost/python/to_python_converter.hpp>
1414# include < boost/python/detail/dealloc.hpp>
1515# include < boost/python/detail/none.hpp>
16+ # include < boost/python/type_id.hpp>
17+ # include < boost/python/errors.hpp>
18+
1619# include < boost/type_traits/remove_pointer.hpp>
1720# include < boost/type_traits/is_pointer.hpp>
21+ # include < boost/type_traits/is_void.hpp>
1822
19- // opaque_pointer_converter --
20- //
21- // usage: opaque_pointer_converter<Pointer>("name")
23+ # include < boost/implicit_cast.hpp>
24+
25+ # include < boost/mpl/eval_if.hpp>
26+ # include < boost/mpl/identity.hpp>
27+ # include < boost/mpl/assert.hpp>
28+
29+ // opaque --
2230//
23- // registers to- and from- python conversions for a type Pointer,
24- // and a corresponding Python type called "name".
31+ // registers to- and from- python conversions for a type Pointee.
2532//
2633// Note:
2734// In addition you need to define specializations for type_id
3138// For an example see libs/python/test/opaque.cpp
3239//
3340namespace boost { namespace python {
34- namespace detail {
35- template <class R >
36- struct opaque_pointer_converter_requires_a_pointer_type
37- # if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__)
38- {}
39- # endif
40- ;
41- }
4241
43- template <class Pointer >
44- struct opaque_pointer_converter
45- : to_python_converter<
46- Pointer, opaque_pointer_converter<Pointer> >
42+ template <class Pointee >
43+ struct opaque
4744{
48- BOOST_STATIC_CONSTANT (
49- bool , ok = is_pointer<Pointer>::value);
50-
51- typedef typename mpl::if_c<
52- ok
53- , Pointer
54- , detail::opaque_pointer_converter_requires_a_pointer_type<Pointer>
55- >::type ptr_type;
56-
45+ opaque ()
46+ {
47+ type_object.tp_name = const_cast <char *>(type_id<Pointee*>().name ());
48+ converter::registry::insert (&extract, type_id<Pointee>());
49+ converter::registry::insert (&wrap, type_id<Pointee*>());
50+ }
51+
52+ static opaque instance;
5753private:
58- struct instance ;
59-
60- public:
61- explicit opaque_pointer_converter (char const * name)
54+
55+ static void * extract (PyObject* op)
6256 {
63- type_object.tp_name = const_cast <char *> (name);
64-
65- lvalue_from_pytype<
66- opaque_pointer_converter<ptr_type>,
67- &opaque_pointer_converter<ptr_type>::type_object
68- >();
57+ return PyObject_TypeCheck (op, &type_object)
58+ ? static_cast <python_instance*>(implicit_cast<void *>(op))->x
59+ : 0
60+ ;
6961 }
7062
71- static PyObject* convert (ptr_type x )
63+ static PyObject* wrap ( void const * px )
7264 {
73- PyObject *result = 0 ;
65+ Pointee* x = * static_cast <Pointee* const *>(px) ;
7466
75- if (x != 0 ) {
76- instance *o = PyObject_New (instance, &type_object );
67+ if (x == 0 )
68+ return detail::none ( );
7769
78- o->x = x;
79- result = &o->base_ ;
80- } else {
81- result = detail::none ();
70+ if ( python_instance *o = PyObject_New (python_instance, &type_object) )
71+ {
72+ o->x = x;
73+ return static_cast <PyObject*>(implicit_cast<void *>(o));
74+ }
75+ else
76+ {
77+ throw error_already_set ();
8278 }
83-
84- return (result);
85- }
86-
87- static typename ::boost::remove_pointer<ptr_type>::type&
88- execute (instance &p_)
89- {
90- return *p_.x ;
9179 }
9280
93- private:
94- static PyTypeObject type_object;
95-
96- // This is a POD so we can use PyObject_Del on it, for example.
97- struct instance
81+ struct python_instance
9882 {
99- PyObject base_;
100- ptr_type x;
83+ PyObject_HEAD
84+ Pointee* x;
10185 };
86+
87+ static PyTypeObject type_object;
10288};
10389
104- template <class Pointer >
105- PyTypeObject opaque_pointer_converter<Pointer>::type_object =
90+ template <class Pointee >
91+ opaque<Pointee> opaque<Pointee>::instance;
92+
93+ template <class Pointee >
94+ PyTypeObject opaque<Pointee>::type_object =
10695{
107- PyObject_HEAD_INIT (NULL )
96+ PyObject_HEAD_INIT (0 )
10897 0 ,
10998 0 ,
110- sizeof (typename opaque_pointer_converter<Pointer >::instance ),
99+ sizeof ( BOOST_DEDUCED_TYPENAME opaque<Pointee >::python_instance ),
111100 0 ,
112101 ::boost::python::detail::dealloc,
113102 0 , /* tp_print */
@@ -155,11 +144,14 @@ PyTypeObject opaque_pointer_converter<Pointer>::type_object =
155144#endif
156145};
157146}} // namespace boost::python
158- # ifdef BOOST_MSVC
159- // MSC works without this workaround, but needs another one ...
160- # define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID (Pointee ) \
161- BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION (Pointee)
147+
148+ # if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
149+
150+ # define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID (Pointee )
151+
162152# else
153+
154+ // If you change the below, don't forget to alter the end of type_id.hpp
163155# define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID (Pointee ) \
164156 namespace boost { namespace python { \
165157 template <> \
@@ -173,6 +165,8 @@ PyTypeObject opaque_pointer_converter<Pointer>::type_object =
173165 { \
174166 return type_info (typeid (Pointee *)); \
175167 } \
176- }}
168+ }}
169+
177170# endif
171+
178172# endif // OPAQUE_POINTER_CONVERTER_HPP_
0 commit comments