[ 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 <boost/python/raw_function.hpp>
44 #include <set>
45 #include <type_traits>
46 
47 namespace vigra {
48 
49 template <class Array>
50 PyObject * returnNumpyArray(Array const & a)
51 {
52  PyObject * pa = a.pyObject();
53  if(pa == 0)
54  PyErr_SetString(PyExc_ValueError, "returnNumpyArray(): Conversion to Python failed, array has no data.");
55  else
56  Py_INCREF(pa);
57  return pa;
58 }
59 
60 VIGRA_EXPORT std::set<std::string> & exportedArrayKeys();
61 
62 template <class ArrayType>
63 struct NumpyArrayConverter {};
64 
65 template <unsigned int N, class T, class Stride>
66 struct NumpyArrayConverter<NumpyArray<N, T, Stride> >
67 {
68  typedef NumpyArray<N, T, Stride> ArrayType;
69  typedef typename ArrayType::ArrayTraits ArrayTraits;
70 
71  NumpyArrayConverter();
72 
73  static void* convertible(PyObject* obj);
74 
75  // from Python
76  static void construct(PyObject* obj,
77  boost::python::converter::rvalue_from_python_stage1_data* data);
78 
79  // to Python
80  static PyObject* convert(ArrayType const& a)
81  {
82  return returnNumpyArray(a);
83  }
84 };
85 
86 template <unsigned int N, class T, class Stride>
87 NumpyArrayConverter<NumpyArray<N, T, Stride> >::NumpyArrayConverter()
88 {
89  using namespace boost::python;
90 
91  converter::registration const * reg = converter::registry::query(type_id<ArrayType>());
92 
93  // register the converters only once
94  if(!reg || !reg->rvalue_chain)
95  {
96  to_python_converter<ArrayType, NumpyArrayConverter>();
97  converter::registry::insert(&convertible, &construct, type_id<ArrayType>());
98  }
99 }
100 
101 template <unsigned int N, class T, class Stride>
102 void * NumpyArrayConverter<NumpyArray<N, T, Stride> >::convertible(PyObject* obj)
103 {
104  bool isCompatible = obj == Py_None || ArrayType::isStrictlyCompatible(obj);
105  // std::cerr << "compatible for " << typeid(NumpyArray<N, T, Stride>).name() << ": " << isCompatible << "\n";
106  return isCompatible
107  ? obj
108  : 0;
109 }
110 
111 // from Python
112 template <unsigned int N, class T, class Stride>
113 void NumpyArrayConverter<NumpyArray<N, T, Stride> >::construct(PyObject* obj,
114  boost::python::converter::rvalue_from_python_stage1_data* data)
115 {
116  void* const storage =
117  ((boost::python::converter::rvalue_from_python_storage<ArrayType>* ) data)->storage.bytes;
118 
119  ArrayType * array = new (storage) ArrayType();
120  if(obj != Py_None)
121  array->makeReferenceUnchecked(obj);
122 
123  data->convertible = storage;
124 }
125 
126 template <unsigned int N, class T, class Stride>
127 struct NumpyArrayConverter<MultiArrayView<N, T, Stride> >
128 : public NumpyArrayConverter<NumpyArray<N, T, Stride> >
129 {
130  typedef NumpyArrayConverter<NumpyArray<N, T, Stride> > BaseType;
131  typedef MultiArrayView<N, T, Stride> ArrayType;
132 
133  NumpyArrayConverter()
134  {
135  using namespace boost::python;
136  converter::registry::insert(&BaseType::convertible, &BaseType::construct,
137  type_id<ArrayType>());
138  }
139 };
140 
141 template <class Iter, class End>
142 struct RegisterNumpyArrayConverters
143 {
144  static void exec()
145  {
146  typedef typename UnqualifiedType<typename boost::mpl::deref<Iter>::type>::type Type;
147  NumpyArrayConverter<Type>();
148  RegisterNumpyArrayConverters<typename boost::mpl::next<Iter>::type, End>::exec();
149  }
150 };
151 
152 template <class End>
153 struct RegisterNumpyArrayConverters<End, End>
154 {
155  static void exec()
156  {}
157 };
158 
159 template <class Typelist>
160 void registerNumpyArrayConverters(Typelist)
161 {
162  RegisterNumpyArrayConverters<typename boost::mpl::begin<Typelist>::type,
163  typename boost::mpl::end<Typelist>::type >::exec();
164 }
165 
166 template <class FN>
167 FN registerConverters(FN f)
168 {
169  registerNumpyArrayConverters(boost::python::detail::get_signature(f));
170  return f;
171 }
172 
173 namespace detail {
174 
175 template <class T>
176 struct TypeName;
177 
178 template <class T>
179 struct TypeName<Singleband<T>>
180 : public TypeName<T>
181 {};
182 
183 template <class T>
184 struct TypeName<Multiband<T>>
185 : public TypeName<T>
186 {};
187 
188 template <class T, int N>
189 struct TypeName<TinyVector<T, N>>
190 : public TypeName<T>
191 {};
192 
193 template <>
194 struct TypeName<void>
195 {
196  static std::string name() {
197  return std::string("void");
198  }
199  static std::string sized_name() {
200  return std::string("void");
201  }
202 };
203 
204 template <>
205 struct TypeName<bool>
206 {
207  static std::string name() {
208  return std::string("bool");
209  }
210  static std::string sized_name() {
211  return std::string("bool8");
212  }
213 };
214 
215 #define VIGRA_SIGNED_INT_NAME(type) \
216 template <> \
217 struct TypeName<type> \
218 { \
219  static std::string name() { \
220  return std::string(#type); \
221  } \
222  static std::string sized_name() { \
223  return std::string("int") + std::to_string(sizeof(type)*8); \
224  } \
225 };
226 
227 VIGRA_SIGNED_INT_NAME(signed char)
228 VIGRA_SIGNED_INT_NAME(short)
229 VIGRA_SIGNED_INT_NAME(int)
230 VIGRA_SIGNED_INT_NAME(long)
231 VIGRA_SIGNED_INT_NAME(long long)
232 
233 #define VIGRA_UNSIGNED_INT_NAME(type) \
234 template <> \
235 struct TypeName<type> \
236 { \
237  static std::string name() { \
238  return std::string(#type); \
239  } \
240  static std::string sized_name() { \
241  return std::string("uint") + std::to_string(sizeof(type)*8); \
242  } \
243 };
244 
245 VIGRA_UNSIGNED_INT_NAME(unsigned char)
246 VIGRA_UNSIGNED_INT_NAME(unsigned short)
247 VIGRA_UNSIGNED_INT_NAME(unsigned int)
248 VIGRA_UNSIGNED_INT_NAME(unsigned long)
249 VIGRA_UNSIGNED_INT_NAME(unsigned long long)
250 
251 #define VIGRA_FLOAT_NAME(type) \
252 template <> \
253 struct TypeName<type> \
254 { \
255  static std::string name() { \
256  return std::string(#type); \
257  } \
258  static std::string sized_name() { \
259  return std::string("float") + std::to_string(sizeof(type)*8); \
260  } \
261 };
262 
263 VIGRA_FLOAT_NAME(float)
264 VIGRA_FLOAT_NAME(double)
265 VIGRA_FLOAT_NAME(long double)
266 
267 #undef VIGRA_SIGNED_INT_NAME
268 #undef VIGRA_UNSIGNED_INT_NAME
269 #undef VIGRA_FLOAT_NAME
270 
271 template <class T = void>
272 struct ExportDoc
273 {
274  static char const * exec(char const *) { return 0; }
275 };
276 
277 template <>
278 struct ExportDoc<void>
279 {
280  static char const * exec(char const * h) { return h; }
281 };
282 
283 } // namespace detail
284 
285 } // namespace vigra
286 
287 namespace boost { namespace python {
288 
289 // Note: Due to a bug in boost::python::docstring_options,
290 // the documentation must always be associated with the
291 // *last* overload, making the functors defined below a
292 // bit more complicated.
293 
294 #define VIGRA_PYTHON_MULTITYPE_FUNCTOR(functor_name, function) \
295 template <class T> \
296 struct functor_name##Impl \
297 { \
298  static void def(const char * pythonName) \
299  { \
300  boost::python::docstring_options doc(false); \
301  boost::python::def(pythonName, vigra::registerConverters(&function<T>)); \
302  } \
303  \
304  template <class Args> \
305  static void def(const char * pythonName, Args const & args) \
306  { \
307  boost::python::docstring_options doc(false); \
308  boost::python::def(pythonName, vigra::registerConverters(&function<T>), args); \
309  } \
310  \
311  static void def(const char * pythonName, char const * help) \
312  { \
313  if(help) \
314  boost::python::def(pythonName, \
315  vigra::registerConverters(&function<T>), help); \
316  else \
317  def(pythonName); \
318  } \
319  \
320  template <class Args> \
321  static void def(const char * pythonName, Args const & args, char const * help) \
322  { \
323  if(help) \
324  boost::python::def(pythonName, \
325  vigra::registerConverters(&function<T>), args, help); \
326  else \
327  def(pythonName, args); \
328  } \
329 }; \
330  \
331 template <> \
332 struct functor_name##Impl<void> \
333 { \
334  static void def(const char *) {} \
335  \
336  template <class A1> \
337  static void def(const char *, A1 const &) {} \
338  \
339  template <class A1, class A2> \
340  static void def(const char *, A1 const &, A2 const &) {} \
341 }; \
342  \
343 template <class T1, \
344  class T2 = void, \
345  class T3 = void, \
346  class T4 = void, \
347  class T5 = void, \
348  class T6 = void, \
349  class T7 = void, \
350  class T8 = void, \
351  class T9 = void, \
352  class T10 = void, \
353  class T11 = void, \
354  class T12 = void> \
355 struct functor_name \
356 : public boost::python::PythonMultidefFunctor \
357 { \
358  bool install_fallback_, show_python_signature_; \
359  \
360  functor_name() \
361  : install_fallback_(false) \
362  , show_python_signature_(true) \
363  {} \
364  \
365  functor_name & installFallback() \
366  { \
367  install_fallback_ = true; \
368  return *this; \
369  } \
370  \
371  functor_name & noPythonSignature() \
372  { \
373  show_python_signature_ = false; \
374  return *this; \
375  } \
376  \
377  typedef boost::python::ArgumentMismatchMessage\
378  <T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> Message; \
379  typedef functor_name##Impl<T1 > F1; \
380  typedef functor_name##Impl<T2 > F2; \
381  typedef functor_name##Impl<T3 > F3; \
382  typedef functor_name##Impl<T4 > F4; \
383  typedef functor_name##Impl<T5 > F5; \
384  typedef functor_name##Impl<T6 > F6; \
385  typedef functor_name##Impl<T7 > F7; \
386  typedef functor_name##Impl<T8 > F8; \
387  typedef functor_name##Impl<T9 > F9; \
388  typedef functor_name##Impl<T10> F10; \
389  typedef functor_name##Impl<T11> F11; \
390  typedef functor_name##Impl<T12> F12; \
391  \
392  void def(const char * pythonName) const \
393  { \
394  boost::python::docstring_options doc(false, false, false); \
395  if(install_fallback_) \
396  Message::def(pythonName); \
397  F1 ::def(pythonName); \
398  F2 ::def(pythonName); \
399  F3 ::def(pythonName); \
400  F4 ::def(pythonName); \
401  F5 ::def(pythonName); \
402  F6 ::def(pythonName); \
403  F7 ::def(pythonName); \
404  F8 ::def(pythonName); \
405  F9 ::def(pythonName); \
406  F10::def(pythonName); \
407  F11::def(pythonName); \
408  F12::def(pythonName); \
409  } \
410  \
411  template <class Args> \
412  void def(const char * pythonName, Args const & args) const \
413  { \
414  boost::python::docstring_options doc(false, false, false); \
415  if(install_fallback_) \
416  Message::def(pythonName); \
417  F1 ::def(pythonName, args); \
418  F2 ::def(pythonName, args); \
419  F3 ::def(pythonName, args); \
420  F4 ::def(pythonName, args); \
421  F5 ::def(pythonName, args); \
422  F6 ::def(pythonName, args); \
423  F7 ::def(pythonName, args); \
424  F8 ::def(pythonName, args); \
425  F9 ::def(pythonName, args); \
426  F10::def(pythonName, args); \
427  F11::def(pythonName, args); \
428  F12::def(pythonName, args); \
429  } \
430  \
431  void def(const char * pythonName, const char * help) const \
432  { \
433  if(install_fallback_) \
434  Message::def(pythonName); \
435  boost::python::docstring_options doc(true, show_python_signature_, false); \
436  F1 ::def(pythonName, detail::ExportDoc<T2 >::exec(help)); \
437  F2 ::def(pythonName, detail::ExportDoc<T3 >::exec(help)); \
438  F3 ::def(pythonName, detail::ExportDoc<T4 >::exec(help)); \
439  F4 ::def(pythonName, detail::ExportDoc<T5 >::exec(help)); \
440  F5 ::def(pythonName, detail::ExportDoc<T6 >::exec(help)); \
441  F6 ::def(pythonName, detail::ExportDoc<T7 >::exec(help)); \
442  F7 ::def(pythonName, detail::ExportDoc<T8 >::exec(help)); \
443  F8 ::def(pythonName, detail::ExportDoc<T9 >::exec(help)); \
444  F9 ::def(pythonName, detail::ExportDoc<T10>::exec(help)); \
445  F10::def(pythonName, detail::ExportDoc<T11>::exec(help)); \
446  F11::def(pythonName, detail::ExportDoc<T12>::exec(help)); \
447  F12::def(pythonName, detail::ExportDoc< >::exec(help)); \
448  } \
449  \
450  template <class Args> \
451  void def(const char * pythonName, Args const & args, char const * help) const \
452  { \
453  if(install_fallback_) \
454  Message::def(pythonName); \
455  boost::python::docstring_options doc(true, show_python_signature_, false); \
456  F1 ::def(pythonName, args, detail::ExportDoc<T2 >::exec(help)); \
457  F2 ::def(pythonName, args, detail::ExportDoc<T3 >::exec(help)); \
458  F3 ::def(pythonName, args, detail::ExportDoc<T4 >::exec(help)); \
459  F4 ::def(pythonName, args, detail::ExportDoc<T5 >::exec(help)); \
460  F5 ::def(pythonName, args, detail::ExportDoc<T6 >::exec(help)); \
461  F6 ::def(pythonName, args, detail::ExportDoc<T7 >::exec(help)); \
462  F7 ::def(pythonName, args, detail::ExportDoc<T8 >::exec(help)); \
463  F8 ::def(pythonName, args, detail::ExportDoc<T9 >::exec(help)); \
464  F9 ::def(pythonName, args, detail::ExportDoc<T10>::exec(help)); \
465  F10::def(pythonName, args, detail::ExportDoc<T11>::exec(help)); \
466  F11::def(pythonName, args, detail::ExportDoc<T12>::exec(help)); \
467  F12::def(pythonName, args, detail::ExportDoc< >::exec(help)); \
468  } \
469 };
470 
471 #define VIGRA_PYTHON_MULTITYPE_FUNCTOR_NDIM(functor_name, function) \
472 template <class T, int FROM, int TO> \
473 struct functor_name##Impl \
474 { \
475  typedef functor_name##Impl type; \
476  \
477  static void def(const char * pythonName) \
478  { \
479  functor_name##Impl<T, FROM, FROM>::def(pythonName); \
480  functor_name##Impl<T, FROM+1, TO>::def(pythonName); \
481  } \
482  \
483  template <class Args> \
484  static void def(const char * pythonName, Args const & args) \
485  { \
486  functor_name##Impl<T, FROM, FROM>::def(pythonName, args); \
487  functor_name##Impl<T, FROM+1, TO>::def(pythonName, args); \
488  } \
489  \
490  static void def(const char * pythonName, char const * help) \
491  { \
492  functor_name##Impl<T, FROM, FROM>::def(pythonName); \
493  functor_name##Impl<T, FROM+1, TO>::def(pythonName, help); \
494  } \
495  \
496  template <class Args> \
497  static void def(const char * pythonName, Args const & args, char const * help) \
498  { \
499  functor_name##Impl<T, FROM, FROM>::def(pythonName, args); \
500  functor_name##Impl<T, FROM+1, TO>::def(pythonName, args, help); \
501  } \
502 }; \
503 \
504 template <class T, int N> \
505 struct functor_name##Impl<T, N, N> \
506 { \
507  typedef functor_name##Impl type; \
508  \
509  static void def(const char * pythonName) \
510  { \
511  boost::python::docstring_options doc(false); \
512  boost::python::def(pythonName, vigra::registerConverters(&function<T, N>)); \
513  } \
514  \
515  template <class Args> \
516  static void def(const char * pythonName, Args const & args) \
517  { \
518  boost::python::docstring_options doc(false); \
519  boost::python::def(pythonName, vigra::registerConverters(&function<T, N>), args); \
520  } \
521  \
522  static void def(const char * pythonName, char const * help) \
523  { \
524  if(help) \
525  boost::python::def(pythonName, \
526  vigra::registerConverters(&function<T, N>), help); \
527  else \
528  def(pythonName); \
529  } \
530  \
531  template <class Args> \
532  static void def(const char * pythonName, Args const & args, char const * help) \
533  { \
534  if(help) \
535  boost::python::def(pythonName, \
536  vigra::registerConverters(&function<T, N>), args, help); \
537  else \
538  def(pythonName, args); \
539  } \
540 }; \
541 \
542 template <int FROM, int TO> \
543 struct functor_name##Impl<void, FROM, TO> \
544 { \
545  static void def(const char *) {} \
546  \
547  template <class A1> \
548  static void def(const char *, A1 const &) {} \
549  \
550  template <class A1, class A2> \
551  static void def(const char *, A1 const &, A2 const &) {} \
552 }; \
553 \
554 template <int N> \
555 struct functor_name##Impl<void, N, N> \
556 { \
557  static void def(const char *) {} \
558  \
559  template <class A1> \
560  static void def(const char *, A1 const &) {} \
561  \
562  template <class A1, class A2> \
563  static void def(const char *, A1 const &, A2 const &) {} \
564 }; \
565 \
566 template <int FROM, int TO, \
567  class T1, \
568  class T2 = void, \
569  class T3 = void, \
570  class T4 = void, \
571  class T5 = void, \
572  class T6 = void, \
573  class T7 = void, \
574  class T8 = void, \
575  class T9 = void, \
576  class T10 = void, \
577  class T11 = void, \
578  class T12 = void> \
579 struct functor_name \
580 : public boost::python::PythonMultidefFunctor \
581 { \
582  bool install_fallback_, show_python_signature_; \
583  \
584  functor_name() \
585  : install_fallback_(false) \
586  , show_python_signature_(true) \
587  { \
588  static_assert(FROM <= TO, #functor_name ": dimension range empty (FROM > TO)"); \
589  } \
590  \
591  functor_name & installFallback() \
592  { \
593  install_fallback_ = true; \
594  return *this; \
595  } \
596  \
597  functor_name & noPythonSignature() \
598  { \
599  show_python_signature_ = false; \
600  return *this; \
601  } \
602  \
603  typedef boost::python::ArgumentMismatchMessage\
604  <T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> Message; \
605  typedef functor_name##Impl<T1 , FROM, TO> F1; \
606  typedef functor_name##Impl<T2 , FROM, TO> F2; \
607  typedef functor_name##Impl<T3 , FROM, TO> F3; \
608  typedef functor_name##Impl<T4 , FROM, TO> F4; \
609  typedef functor_name##Impl<T5 , FROM, TO> F5; \
610  typedef functor_name##Impl<T6 , FROM, TO> F6; \
611  typedef functor_name##Impl<T7 , FROM, TO> F7; \
612  typedef functor_name##Impl<T8 , FROM, TO> F8; \
613  typedef functor_name##Impl<T9 , FROM, TO> F9; \
614  typedef functor_name##Impl<T10, FROM, TO> F10; \
615  typedef functor_name##Impl<T11, FROM, TO> F11; \
616  typedef functor_name##Impl<T12, FROM, TO> F12; \
617  \
618  void def(const char * pythonName) const \
619  { \
620  boost::python::docstring_options doc(false, false, false); \
621  if(install_fallback_) \
622  Message::def(pythonName); \
623  F1 ::def(pythonName); \
624  F2 ::def(pythonName); \
625  F3 ::def(pythonName); \
626  F4 ::def(pythonName); \
627  F5 ::def(pythonName); \
628  F6 ::def(pythonName); \
629  F7 ::def(pythonName); \
630  F8 ::def(pythonName); \
631  F9 ::def(pythonName); \
632  F10::def(pythonName); \
633  F11::def(pythonName); \
634  F12::def(pythonName); \
635  } \
636  \
637  template <class Args> \
638  void def(const char * pythonName, Args const & args) const \
639  { \
640  boost::python::docstring_options doc(false, false, false); \
641  if(install_fallback_) \
642  Message::def(pythonName); \
643  F1 ::def(pythonName, args); \
644  F2 ::def(pythonName, args); \
645  F3 ::def(pythonName, args); \
646  F4 ::def(pythonName, args); \
647  F5 ::def(pythonName, args); \
648  F6 ::def(pythonName, args); \
649  F7 ::def(pythonName, args); \
650  F8 ::def(pythonName, args); \
651  F9 ::def(pythonName, args); \
652  F10::def(pythonName, args); \
653  F11::def(pythonName, args); \
654  F12::def(pythonName, args); \
655  } \
656  \
657  void def(const char * pythonName, const char * help) const \
658  { \
659  if(install_fallback_) \
660  Message::def(pythonName); \
661  boost::python::docstring_options doc(true, show_python_signature_, false); \
662  F1 ::def(pythonName, detail::ExportDoc<T2 >::exec(help)); \
663  F2 ::def(pythonName, detail::ExportDoc<T3 >::exec(help)); \
664  F3 ::def(pythonName, detail::ExportDoc<T4 >::exec(help)); \
665  F4 ::def(pythonName, detail::ExportDoc<T5 >::exec(help)); \
666  F5 ::def(pythonName, detail::ExportDoc<T6 >::exec(help)); \
667  F6 ::def(pythonName, detail::ExportDoc<T7 >::exec(help)); \
668  F7 ::def(pythonName, detail::ExportDoc<T8 >::exec(help)); \
669  F8 ::def(pythonName, detail::ExportDoc<T9 >::exec(help)); \
670  F9 ::def(pythonName, detail::ExportDoc<T10>::exec(help)); \
671  F10::def(pythonName, detail::ExportDoc<T11>::exec(help)); \
672  F11::def(pythonName, detail::ExportDoc<T12>::exec(help)); \
673  F12::def(pythonName, detail::ExportDoc< >::exec(help)); \
674  } \
675  \
676  template <class Args> \
677  void def(const char * pythonName, Args const & args, char const * help) const \
678  { \
679  if(install_fallback_) \
680  Message::def(pythonName); \
681  boost::python::docstring_options doc(true, show_python_signature_, false); \
682  F1 ::def(pythonName, args, detail::ExportDoc<T2 >::exec(help)); \
683  F2 ::def(pythonName, args, detail::ExportDoc<T3 >::exec(help)); \
684  F3 ::def(pythonName, args, detail::ExportDoc<T4 >::exec(help)); \
685  F4 ::def(pythonName, args, detail::ExportDoc<T5 >::exec(help)); \
686  F5 ::def(pythonName, args, detail::ExportDoc<T6 >::exec(help)); \
687  F6 ::def(pythonName, args, detail::ExportDoc<T7 >::exec(help)); \
688  F7 ::def(pythonName, args, detail::ExportDoc<T8 >::exec(help)); \
689  F8 ::def(pythonName, args, detail::ExportDoc<T9 >::exec(help)); \
690  F9 ::def(pythonName, args, detail::ExportDoc<T10>::exec(help)); \
691  F10::def(pythonName, args, detail::ExportDoc<T11>::exec(help)); \
692  F11::def(pythonName, args, detail::ExportDoc<T12>::exec(help)); \
693  F12::def(pythonName, args, detail::ExportDoc< >::exec(help)); \
694  } \
695 };
696 
697 struct PythonMultidefFunctor {};
698 
699 template <class T1,
700  class T2 = void,
701  class T3 = void,
702  class T4 = void,
703  class T5 = void,
704  class T6 = void,
705  class T7 = void,
706  class T8 = void,
707  class T9 = void,
708  class T10 = void,
709  class T11 = void,
710  class T12 = void>
711 struct ArgumentMismatchMessage
712 {
713  static std::string message()
714  {
715  std::string res(
716  "No C++ overload matches the arguments. This can have three reasons:\n\n"
717  " * The array arguments may have an unsupported element type. You may need\n"
718  " to convert your array(s) to another element type using 'array.astype(...)'.\n"
719  " The function currently supports the following types:\n\n ");
720  res += vigra::detail::TypeName<T1>::sized_name();
721 
722  if(vigra::detail::TypeName<T2>::sized_name() != "void")
723  res += ", " + vigra::detail::TypeName<T2>::sized_name();
724  if(vigra::detail::TypeName<T3>::sized_name() != "void")
725  res += ", " + vigra::detail::TypeName<T3>::sized_name();
726  if(vigra::detail::TypeName<T4>::sized_name() != "void")
727  res += ", " + vigra::detail::TypeName<T4>::sized_name();
728  if(vigra::detail::TypeName<T5>::sized_name() != "void")
729  res += ", " + vigra::detail::TypeName<T5>::sized_name();
730  if(vigra::detail::TypeName<T6>::sized_name() != "void")
731  res += ", " + vigra::detail::TypeName<T6>::sized_name();
732  if(vigra::detail::TypeName<T7>::sized_name() != "void")
733  res += ", " + vigra::detail::TypeName<T7>::sized_name();
734  if(vigra::detail::TypeName<T8>::sized_name() != "void")
735  res += ", " + vigra::detail::TypeName<T8>::sized_name();
736  if(vigra::detail::TypeName<T9>::sized_name() != "void")
737  res += ", " + vigra::detail::TypeName<T9>::sized_name();
738  if(vigra::detail::TypeName<T10>::sized_name() != "void")
739  res += ", " + vigra::detail::TypeName<T10>::sized_name();
740  if(vigra::detail::TypeName<T11>::sized_name() != "void")
741  res += ", " + vigra::detail::TypeName<T11>::sized_name();
742  if(vigra::detail::TypeName<T12>::sized_name() != "void")
743  res += ", " + vigra::detail::TypeName<T12>::sized_name();
744 
745  res +=
746  "\n\n"
747  " * The dimension of your array(s) is currently unsupported (consult the\n"
748  " function's documentation for information about supported dimensions).\n\n"
749  " * You provided an unrecognized argument, or an argument with incorrect type\n"
750  " (consult the documentation for valid function signatures).\n\n"
751  "Additional overloads can easily be added in the vigranumpy C++ sources.\n"
752  "Please submit an issue at http://github.com/ukoethe/vigra/ to let us know\n"
753  "what you need (or a pull request if you solved it on your own :-).\n\n";
754 
755  return res;
756  }
757 
758  static void def(const char * pythonName)
759  {
760  docstring_options doc(false, false, false);
761  std::string msg = message(),
762  module = extract<std::string>(scope().attr("__name__"))() + ".";
763  msg += "Type 'help(" + module + pythonName + ")' to get full documentation.\n";
764  boost::python::def(pythonName,
765  raw_function([msg](tuple, dict) -> object {
766  throw std::invalid_argument(msg);
767  return object();
768  }, 0));
769  }
770 };
771 
772 // in the sequel, the doc string is only registered with the last
773 // overload, so that it shows up only once
774 template <class Functor>
775 inline typename std::enable_if<std::is_base_of<PythonMultidefFunctor, Functor>::value,
776  void>::type
777 multidef(char const* python_name, Functor const & f)
778 {
779  f.def(python_name);
780 }
781 
782 template <class Functor, class Args>
783 inline typename std::enable_if<std::is_base_of<PythonMultidefFunctor, Functor>::value,
784  void>::type
785 multidef(char const* python_name, Functor const & f, Args const& args)
786 {
787  f.def(python_name, args);
788 }
789 
790 template <class Functor>
791 inline typename std::enable_if<std::is_base_of<PythonMultidefFunctor, Functor>::value,
792  void>::type
793 multidef(char const* python_name, Functor const & f, const char * help)
794 {
795  f.def(python_name, help);
796 }
797 
798 template <class Functor, class Args>
799 inline typename std::enable_if<std::is_base_of<PythonMultidefFunctor, Functor>::value,
800  void>::type
801 multidef(char const* python_name, Functor const & f, Args const& args, const char * help)
802 {
803  f.def(python_name, args, help);
804 }
805 
806 // overload def() such that it advises to use multidef() instead
807 template <class Functor>
808 inline typename std::enable_if<std::is_base_of<PythonMultidefFunctor, Functor>::value,
809  void>::type
810 def(char const*, Functor const &)
811 {
812  static_assert(!std::is_base_of<PythonMultidefFunctor, Functor>::value,
813  "def(): use multidef() to export multiple overloads.");
814 }
815 
816 template <class Functor, class Args>
817 inline typename std::enable_if<std::is_base_of<PythonMultidefFunctor, Functor>::value,
818  void>::type
819 def(char const*, Functor const &, Args const& )
820 {
821  static_assert(!std::is_base_of<PythonMultidefFunctor, Functor>::value,
822  "def(): use multidef() to export multiple overloads.");
823 }
824 
825 template <class Functor>
826 inline typename std::enable_if<std::is_base_of<PythonMultidefFunctor, Functor>::value,
827  void>::type
828 def(char const*, Functor const &, const char *)
829 {
830  static_assert(!std::is_base_of<PythonMultidefFunctor, Functor>::value,
831  "def(): use multidef() to export multiple overloads.");
832 }
833 
834 template <class Functor, class Args>
835 inline typename std::enable_if<std::is_base_of<PythonMultidefFunctor, Functor>::value,
836  void>::type
837 def(char const*, Functor const &, Args const&, const char *)
838 {
839  static_assert(!std::is_base_of<PythonMultidefFunctor, Functor>::value,
840  "def(): use multidef() to export multiple overloads.");
841 }
842 
843 }} // namespace boost::python
844 
845 #endif // VIGRA_NUMPY_ARRAY_CONVERTERS_HXX

© 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.11.1 (Fri May 19 2017)