vigra - vigra/numpy_array_converters.hxx Source File

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

numpy_array_converters.hxx |

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)