Chris@16
|
1 // Copyright Gottfried Ganßauge 2003..2006.
|
Chris@16
|
2 // Distributed under the Boost Software License, Version 1.0. (See
|
Chris@16
|
3 // accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
4 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
5 /*
|
Chris@16
|
6 * Generic Conversion of opaque C++-pointers to a Python-Wrapper.
|
Chris@16
|
7 */
|
Chris@16
|
8 # ifndef OPAQUE_POINTER_CONVERTER_HPP_
|
Chris@16
|
9 # define OPAQUE_POINTER_CONVERTER_HPP_
|
Chris@16
|
10
|
Chris@16
|
11 # include <boost/python/detail/prefix.hpp>
|
Chris@16
|
12 # include <boost/python/lvalue_from_pytype.hpp>
|
Chris@16
|
13 # include <boost/python/to_python_converter.hpp>
|
Chris@16
|
14 # include <boost/python/converter/registrations.hpp>
|
Chris@16
|
15 # include <boost/python/detail/dealloc.hpp>
|
Chris@16
|
16 # include <boost/python/detail/none.hpp>
|
Chris@16
|
17 # include <boost/python/type_id.hpp>
|
Chris@16
|
18 # include <boost/python/errors.hpp>
|
Chris@16
|
19
|
Chris@16
|
20 # include <boost/type_traits/remove_pointer.hpp>
|
Chris@16
|
21 # include <boost/type_traits/is_pointer.hpp>
|
Chris@16
|
22 # include <boost/type_traits/is_void.hpp>
|
Chris@16
|
23
|
Chris@16
|
24 # include <boost/implicit_cast.hpp>
|
Chris@16
|
25
|
Chris@16
|
26 # include <boost/mpl/eval_if.hpp>
|
Chris@16
|
27 # include <boost/mpl/identity.hpp>
|
Chris@16
|
28 # include <boost/mpl/assert.hpp>
|
Chris@16
|
29
|
Chris@16
|
30 // opaque --
|
Chris@16
|
31 //
|
Chris@16
|
32 // registers to- and from- python conversions for a type Pointee.
|
Chris@16
|
33 //
|
Chris@16
|
34 // Note:
|
Chris@16
|
35 // In addition you need to define specializations for type_id
|
Chris@16
|
36 // on the type pointed to by Pointer using
|
Chris@16
|
37 // BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee)
|
Chris@16
|
38 //
|
Chris@16
|
39 // For an example see libs/python/test/opaque.cpp
|
Chris@16
|
40 //
|
Chris@16
|
41 namespace boost { namespace python {
|
Chris@16
|
42
|
Chris@16
|
43 template <class Pointee>
|
Chris@16
|
44 struct opaque
|
Chris@16
|
45 {
|
Chris@16
|
46 opaque()
|
Chris@16
|
47 {
|
Chris@16
|
48 if (type_object.tp_name == 0)
|
Chris@16
|
49 {
|
Chris@16
|
50 type_object.tp_name = const_cast<char*>(type_id<Pointee*>().name());
|
Chris@16
|
51 if (PyType_Ready (&type_object) < 0)
|
Chris@16
|
52 {
|
Chris@16
|
53 throw error_already_set();
|
Chris@16
|
54 }
|
Chris@16
|
55
|
Chris@16
|
56 this->register_self();
|
Chris@16
|
57 }
|
Chris@16
|
58 }
|
Chris@16
|
59
|
Chris@16
|
60 static opaque instance;
|
Chris@16
|
61 private:
|
Chris@16
|
62
|
Chris@16
|
63 static void* extract(PyObject* op)
|
Chris@16
|
64 {
|
Chris@16
|
65 return PyObject_TypeCheck(op, &type_object)
|
Chris@16
|
66 ? static_cast<python_instance*>(implicit_cast<void*>(op))->x
|
Chris@16
|
67 : 0
|
Chris@16
|
68 ;
|
Chris@16
|
69 }
|
Chris@16
|
70
|
Chris@16
|
71 static PyObject* wrap(void const* px)
|
Chris@16
|
72 {
|
Chris@16
|
73 Pointee* x = *static_cast<Pointee*const*>(px);
|
Chris@16
|
74
|
Chris@16
|
75 if (x == 0)
|
Chris@16
|
76 return detail::none();
|
Chris@16
|
77
|
Chris@16
|
78 if ( python_instance *o = PyObject_New(python_instance, &type_object) )
|
Chris@16
|
79 {
|
Chris@16
|
80 o->x = x;
|
Chris@16
|
81 return static_cast<PyObject*>(implicit_cast<void*>(o));
|
Chris@16
|
82 }
|
Chris@16
|
83 else
|
Chris@16
|
84 {
|
Chris@16
|
85 throw error_already_set();
|
Chris@16
|
86 }
|
Chris@16
|
87 }
|
Chris@16
|
88
|
Chris@16
|
89 void register_self()
|
Chris@16
|
90 {
|
Chris@16
|
91 converter::registration const *existing =
|
Chris@16
|
92 converter::registry::query (type_id<Pointee*>());
|
Chris@16
|
93
|
Chris@16
|
94 if ((existing == 0) || (existing->m_to_python == 0))
|
Chris@16
|
95 {
|
Chris@16
|
96 #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
Chris@16
|
97 converter::registry::insert(&extract, type_id<Pointee>(), &get_pytype);
|
Chris@16
|
98 converter::registry::insert(&wrap, type_id<Pointee*>(), &get_pytype);
|
Chris@16
|
99 #else
|
Chris@16
|
100 converter::registry::insert(&extract, type_id<Pointee>());
|
Chris@16
|
101 converter::registry::insert(&wrap, type_id<Pointee*>());
|
Chris@16
|
102 #endif
|
Chris@16
|
103 }
|
Chris@16
|
104 }
|
Chris@16
|
105
|
Chris@16
|
106 struct python_instance
|
Chris@16
|
107 {
|
Chris@16
|
108 PyObject_HEAD
|
Chris@16
|
109 Pointee* x;
|
Chris@16
|
110 };
|
Chris@16
|
111
|
Chris@16
|
112 static PyTypeObject type_object;
|
Chris@16
|
113 #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
Chris@16
|
114 static PyTypeObject const *get_pytype(){return &type_object; }
|
Chris@16
|
115 #endif
|
Chris@16
|
116 };
|
Chris@16
|
117
|
Chris@16
|
118 template <class Pointee>
|
Chris@16
|
119 opaque<Pointee> opaque<Pointee>::instance;
|
Chris@16
|
120
|
Chris@16
|
121 template <class Pointee>
|
Chris@16
|
122 PyTypeObject opaque<Pointee>::type_object =
|
Chris@16
|
123 {
|
Chris@16
|
124 PyVarObject_HEAD_INIT(NULL, 0)
|
Chris@16
|
125 0,
|
Chris@16
|
126 sizeof( BOOST_DEDUCED_TYPENAME opaque<Pointee>::python_instance ),
|
Chris@16
|
127 0,
|
Chris@16
|
128 ::boost::python::detail::dealloc,
|
Chris@16
|
129 0, /* tp_print */
|
Chris@16
|
130 0, /* tp_getattr */
|
Chris@16
|
131 0, /* tp_setattr */
|
Chris@16
|
132 0, /* tp_compare */
|
Chris@16
|
133 0, /* tp_repr */
|
Chris@16
|
134 0, /* tp_as_number */
|
Chris@16
|
135 0, /* tp_as_sequence */
|
Chris@16
|
136 0, /* tp_as_mapping */
|
Chris@16
|
137 0, /* tp_hash */
|
Chris@16
|
138 0, /* tp_call */
|
Chris@16
|
139 0, /* tp_str */
|
Chris@16
|
140 0, /* tp_getattro */
|
Chris@16
|
141 0, /* tp_setattro */
|
Chris@16
|
142 0, /* tp_as_buffer */
|
Chris@16
|
143 0, /* tp_flags */
|
Chris@16
|
144 0, /* tp_doc */
|
Chris@16
|
145 0, /* tp_traverse */
|
Chris@16
|
146 0, /* tp_clear */
|
Chris@16
|
147 0, /* tp_richcompare */
|
Chris@16
|
148 0, /* tp_weaklistoffset */
|
Chris@16
|
149 0, /* tp_iter */
|
Chris@16
|
150 0, /* tp_iternext */
|
Chris@16
|
151 0, /* tp_methods */
|
Chris@16
|
152 0, /* tp_members */
|
Chris@16
|
153 0, /* tp_getset */
|
Chris@16
|
154 0, /* tp_base */
|
Chris@16
|
155 0, /* tp_dict */
|
Chris@16
|
156 0, /* tp_descr_get */
|
Chris@16
|
157 0, /* tp_descr_set */
|
Chris@16
|
158 0, /* tp_dictoffset */
|
Chris@16
|
159 0, /* tp_init */
|
Chris@16
|
160 0, /* tp_alloc */
|
Chris@16
|
161 0, /* tp_new */
|
Chris@16
|
162 0, /* tp_free */
|
Chris@16
|
163 0, /* tp_is_gc */
|
Chris@16
|
164 0, /* tp_bases */
|
Chris@16
|
165 0, /* tp_mro */
|
Chris@16
|
166 0, /* tp_cache */
|
Chris@16
|
167 0, /* tp_subclasses */
|
Chris@16
|
168 0, /* tp_weaklist */
|
Chris@16
|
169 #if PYTHON_API_VERSION >= 1012
|
Chris@16
|
170 0 /* tp_del */
|
Chris@16
|
171 #endif
|
Chris@16
|
172 };
|
Chris@16
|
173 }} // namespace boost::python
|
Chris@16
|
174
|
Chris@16
|
175 # if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
Chris@16
|
176
|
Chris@16
|
177 # define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee)
|
Chris@16
|
178
|
Chris@16
|
179 # else
|
Chris@16
|
180
|
Chris@16
|
181 // If you change the below, don't forget to alter the end of type_id.hpp
|
Chris@16
|
182 # define BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee) \
|
Chris@16
|
183 namespace boost { namespace python { \
|
Chris@16
|
184 template<> \
|
Chris@16
|
185 inline type_info type_id<Pointee>(BOOST_PYTHON_EXPLICIT_TT_DEF(Pointee)) \
|
Chris@16
|
186 { \
|
Chris@16
|
187 return type_info (typeid (Pointee *)); \
|
Chris@16
|
188 } \
|
Chris@16
|
189 template<> \
|
Chris@16
|
190 inline type_info type_id<const volatile Pointee&>( \
|
Chris@16
|
191 BOOST_PYTHON_EXPLICIT_TT_DEF(const volatile Pointee&)) \
|
Chris@16
|
192 { \
|
Chris@16
|
193 return type_info (typeid (Pointee *)); \
|
Chris@16
|
194 } \
|
Chris@16
|
195 }}
|
Chris@16
|
196
|
Chris@16
|
197 # endif
|
Chris@16
|
198
|
Chris@16
|
199 # endif // OPAQUE_POINTER_CONVERTER_HPP_
|