[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

numpy_array_converters.hxx VIGRA

1 /************************************************************************/
2 /* */
3 /* Copyright 2009 by Ullrich Koethe and Hans Meine */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35 
36 #ifndef VIGRA_NUMPY_ARRAY_CONVERTERS_HXX
37 #define VIGRA_NUMPY_ARRAY_CONVERTERS_HXX
38 
39 #include "numpy_array.hxx"
40 #include "metaprogramming.hxx"
41 #include <boost/python.hpp>
42 #include <boost/python/to_python_converter.hpp>
43 #include <set>
44 
45 namespace vigra {
46 
47 template <class Array>
48 PyObject * returnNumpyArray(Array const & a)
49 {
50  PyObject * pa = a.pyObject();
51  if(pa == 0)
52  PyErr_SetString(PyExc_ValueError, "returnNumpyArray(): Conversion to Python failed, array has no data.");
53  else
54  Py_INCREF(pa);
55  return pa;
56 }
57 
58 VIGRA_EXPORT std::set<std::string> & exportedArrayKeys();
59 
60 template <class ArrayType>
61 struct NumpyArrayConverter {};
62 
63 template <unsigned int N, class T, class Stride>
64 struct NumpyArrayConverter<NumpyArray<N, T, Stride> >
65 {
66  typedef NumpyArray<N, T, Stride> ArrayType;
67  typedef typename ArrayType::ArrayTraits ArrayTraits;
68 
69  NumpyArrayConverter();
70 
71  static void* convertible(PyObject* obj);
72 
73  // from Python
74  static void construct(PyObject* obj,
75  boost::python::converter::rvalue_from_python_stage1_data* data);
76 
77  // to Python
78  static PyObject* convert(ArrayType const& a)
79  {
80  return returnNumpyArray(a);
81  }
82 };
83 
84 template <unsigned int N, class T, class Stride>
85 NumpyArrayConverter<NumpyArray<N, T, Stride> >::NumpyArrayConverter()
86 {
87  using namespace boost::python;
88 
89  converter::registration const * reg = converter::registry::query(type_id<ArrayType>());
90 
91  // register the to_python_converter only once
92  // FIXME: I'm not sure if this is correct.
93  if(!reg || !reg->rvalue_chain)
94  {
95  to_python_converter<ArrayType, NumpyArrayConverter>();
96  }
97  converter::registry::insert(&convertible, &construct, type_id<ArrayType>());
98 }
99 
100 template <unsigned int N, class T, class Stride>
101 void * NumpyArrayConverter<NumpyArray<N, T, Stride> >::convertible(PyObject* obj)
102 {
103  bool isCompatible = obj == Py_None || ArrayType::isStrictlyCompatible(obj);
104  // std::cerr << "compatible for " << typeid(NumpyArray<N, T, Stride>).name() << ": " << isCompatible << "\n";
105  return isCompatible
106  ? obj
107  : 0;
108 }
109 
110 // from Python
111 template <unsigned int N, class T, class Stride>
112 void NumpyArrayConverter<NumpyArray<N, T, Stride> >::construct(PyObject* obj,
113  boost::python::converter::rvalue_from_python_stage1_data* data)
114 {
115  void* const storage =
116  ((boost::python::converter::rvalue_from_python_storage<ArrayType>* ) data)->storage.bytes;
117 
118  ArrayType * array = new (storage) ArrayType();
119  if(obj != Py_None)
120  array->makeReferenceUnchecked(obj);
121 
122  data->convertible = storage;
123 }
124 
125 template <unsigned int N, class T, class Stride>
126 struct NumpyArrayConverter<MultiArrayView<N, T, Stride> >
127 : public NumpyArrayConverter<NumpyArray<N, T, Stride> >
128 {
129  typedef NumpyArrayConverter<NumpyArray<N, T, Stride> > BaseType;
130  typedef MultiArrayView<N, T, Stride> ArrayType;
131 
132  NumpyArrayConverter()
133  {
134  using namespace boost::python;
135  converter::registry::insert(&BaseType::convertible, &BaseType::construct,
136  type_id<ArrayType>());
137  }
138 };
139 
140 template <class Iter, class End>
141 struct RegisterNumpyArrayConverters
142 {
143  static void exec()
144  {
145  typedef typename UnqualifiedType<typename boost::mpl::deref<Iter>::type>::type Type;
146  NumpyArrayConverter<Type>();
147  RegisterNumpyArrayConverters<typename boost::mpl::next<Iter>::type, End>::exec();
148  }
149 };
150 
151 template <class End>
152 struct RegisterNumpyArrayConverters<End, End>
153 {
154  static void exec()
155  {}
156 };
157 
158 template <class Typelist>
159 void registerNumpyArrayConverters(Typelist)
160 {
161  RegisterNumpyArrayConverters<typename boost::mpl::begin<Typelist>::type,
162  typename boost::mpl::end<Typelist>::type >::exec();
163 }
164 
165 template <class FN>
166 FN registerConverters(FN f)
167 {
168  registerNumpyArrayConverters(boost::python::detail::get_signature(f));
169  return f;
170 }
171 
172 
173 } // namespace vigra
174 
175 namespace boost { namespace python {
176 
177 #define VIGRA_PYTHON_MULTITYPE_FUNCTOR(functor_name, function) \
178 template <class T> \
179 struct functor_name##Impl \
180 { \
181  typedef functor_name##Impl type; \
182  \
183  static void def(const char * pythonName) \
184  { \
185  boost::python::def(pythonName, vigra::registerConverters(&function<T>)); \
186  } \
187  \
188  template <class A1> \
189  static void def(const char * pythonName, A1 const & a1) \
190  { \
191  boost::python::def(pythonName, vigra::registerConverters(&function<T>), a1); \
192  } \
193  \
194  template <class A1, class A2> \
195  static void def(const char * pythonName, A1 const & a1, A2 const & a2) \
196  { \
197  boost::python::def(pythonName, vigra::registerConverters(&function<T>), a1, a2); \
198  } \
199  \
200  template <class A1, class A2, class A3> \
201  static void def(const char * pythonName, A1 const & a1, A2 const & a2, A3 const & a3) \
202  { \
203  boost::python::def(pythonName, vigra::registerConverters(&function<T>), a1, a2, a3); \
204  } \
205 }; \
206  \
207 template <> \
208 struct functor_name##Impl<void> \
209 { \
210  typedef void type; \
211 }; \
212  \
213 template <class T1, \
214  class T2 = void, \
215  class T3 = void, \
216  class T4 = void, \
217  class T5 = void, \
218  class T6 = void, \
219  class T7 = void, \
220  class T8 = void, \
221  class T9 = void, \
222  class T10 = void, \
223  class T11 = void, \
224  class T12 = void> \
225 struct functor_name \
226 : public boost::python::TypeList<typename functor_name##Impl<T1>::type, \
227  boost::python::TypeList<typename functor_name##Impl<T2>::type, \
228  boost::python::TypeList<typename functor_name##Impl<T3>::type, \
229  boost::python::TypeList<typename functor_name##Impl<T4>::type, \
230  boost::python::TypeList<typename functor_name##Impl<T5>::type, \
231  boost::python::TypeList<typename functor_name##Impl<T6>::type, \
232  boost::python::TypeList<typename functor_name##Impl<T7>::type, \
233  boost::python::TypeList<typename functor_name##Impl<T8>::type, \
234  boost::python::TypeList<typename functor_name##Impl<T9>::type, \
235  boost::python::TypeList<typename functor_name##Impl<T10>::type, \
236  boost::python::TypeList<typename functor_name##Impl<T11>::type, \
237  boost::python::TypeList<typename functor_name##Impl<T12>::type, \
238  boost::python::TypeList<void, void> > > > > > > > > > > > > \
239 {};
240 
241 #define VIGRA_PYTHON_MULTITYPE_FUNCTOR_NDIM(functor_name, function) \
242 template <class T, int N> \
243 struct functor_name##Impl \
244 { \
245  typedef functor_name##Impl type; \
246  \
247  static void def(const char * pythonName) \
248  { \
249  boost::python::def(pythonName, vigra::registerConverters(&function<T, N>)); \
250  } \
251  \
252  template <class A1> \
253  static void def(const char * pythonName, A1 const & a1) \
254  { \
255  boost::python::def(pythonName, vigra::registerConverters(&function<T, N>), a1); \
256  } \
257  \
258  template <class A1, class A2> \
259  static void def(const char * pythonName, A1 const & a1, A2 const & a2) \
260  { \
261  boost::python::def(pythonName, vigra::registerConverters(&function<T, N>), a1, a2); \
262  } \
263  \
264  template <class A1, class A2, class A3> \
265  static void def(const char * pythonName, A1 const & a1, A2 const & a2, A3 const & a3) \
266  { \
267  boost::python::def(pythonName, vigra::registerConverters(&function<T, N>), a1, a2, a3); \
268  } \
269 }; \
270  \
271 template <int N> \
272 struct functor_name##Impl<void, N> \
273 { \
274  typedef void type; \
275 }; \
276  \
277 template <int N, \
278  class T1, \
279  class T2 = void, \
280  class T3 = void, \
281  class T4 = void, \
282  class T5 = void, \
283  class T6 = void, \
284  class T7 = void, \
285  class T8 = void, \
286  class T9 = void, \
287  class T10 = void, \
288  class T11 = void, \
289  class T12 = void> \
290 struct functor_name \
291 : public boost::python::TypeList<typename functor_name##Impl<T1, N>::type, \
292  boost::python::TypeList<typename functor_name##Impl<T2, N>::type, \
293  boost::python::TypeList<typename functor_name##Impl<T3, N>::type, \
294  boost::python::TypeList<typename functor_name##Impl<T4, N>::type, \
295  boost::python::TypeList<typename functor_name##Impl<T5, N>::type, \
296  boost::python::TypeList<typename functor_name##Impl<T6, N>::type, \
297  boost::python::TypeList<typename functor_name##Impl<T7, N>::type, \
298  boost::python::TypeList<typename functor_name##Impl<T8, N>::type, \
299  boost::python::TypeList<typename functor_name##Impl<T9, N>::type, \
300  boost::python::TypeList<typename functor_name##Impl<T10, N>::type, \
301  boost::python::TypeList<typename functor_name##Impl<T11, N>::type, \
302  boost::python::TypeList<typename functor_name##Impl<T12, N>::type, \
303  boost::python::TypeList<void, void> > > > > > > > > > > > > \
304 {};
305 
306 template <class Head, class Tail>
307 struct TypeList
308 {
309  typedef Head head;
310  typedef Tail tail;
311 };
312 
313 // in the sequel, the doc string is only registered with the last
314 // overload, so that it shows up only once
315 template <class Head, class Tail>
316 inline void multidef(char const* functor_name, TypeList<Head, Tail>)
317 {
318  Head::def(functor_name);
319  multidef(functor_name, Tail());
320 }
321 
322 template <class Head, class Tail>
323 inline void multidef(char const* functor_name, TypeList<Head, Tail>, const char * help)
324 {
325  Head::def(functor_name);
326  multidef(functor_name, Tail(), help);
327 }
328 
329 template <class Head, class Tail, class Args>
330 inline void multidef(char const* functor_name, TypeList<Head, Tail>, Args const& args)
331 {
332  Head::def(functor_name, args);
333  multidef(functor_name, Tail(), args);
334 }
335 
336 template <class Head, class Tail, class Args>
337 inline void multidef(char const* functor_name, TypeList<Head, Tail>, Args const& args, char const * help)
338 {
339  Head::def(functor_name, args);
340  multidef(functor_name, Tail(), args, help);
341 }
342 
343 template <class Head, class Tail>
344 inline void multidef(char const* functor_name, TypeList<Head, TypeList<void, Tail> >)
345 {
346  Head::def(functor_name);
347 }
348 
349 template <class Head, class Tail, class Args>
350 inline void multidef(char const* functor_name, TypeList<Head, TypeList<void, Tail> >, Args const& args)
351 {
352  Head::def(functor_name, args);
353 }
354 
355 template <class Head, class Tail>
356 inline void multidef(char const* functor_name, TypeList<Head, TypeList<void, Tail> >, const char * help)
357 {
358  Head::def(functor_name, help);
359 }
360 
361 template <class Head, class Tail, class Args>
362 inline void multidef(char const* functor_name, TypeList<Head, TypeList<void, Tail> >, Args const& args, const char * help)
363 {
364  Head::def(functor_name, args, help);
365 }
366 
367 }} // namespace boost::python
368 
369 #endif // VIGRA_NUMPY_ARRAY_CONVERTERS_HXX
Definition: adjacency_list_graph.hxx:1087
Definition: accessor.hxx:43
Definition: numpy_array_converters.hxx:175

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.10.0