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