[ 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
47namespace vigra {
48
49template <class Array>
50PyObject * 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
60VIGRA_EXPORT std::set<std::string> & exportedArrayKeys();
61
62template <class ArrayType>
63struct NumpyArrayConverter {};
64
65template <unsigned int N, class T, class Stride>
66struct 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
86template <unsigned int N, class T, class Stride>
87NumpyArrayConverter<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
101template <unsigned int N, class T, class Stride>
102void * 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
112template <unsigned int N, class T, class Stride>
113void 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
126template <unsigned int N, class T, class Stride>
127struct 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
141template <class Iter, class End>
142struct 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
152template <class End>
153struct RegisterNumpyArrayConverters<End, End>
154{
155 static void exec()
156 {}
157};
158
159template <class Typelist>
160void registerNumpyArrayConverters(Typelist)
161{
162 RegisterNumpyArrayConverters<typename boost::mpl::begin<Typelist>::type,
163 typename boost::mpl::end<Typelist>::type >::exec();
164}
165
166template <class FN>
167FN registerConverters(FN f)
168{
169 registerNumpyArrayConverters(boost::python::detail::get_signature(f));
170 return f;
171}
172
173namespace detail {
174
175template <class T>
176struct TypeName;
177
178template <class T>
179struct TypeName<Singleband<T>>
180: public TypeName<T>
181{};
182
183template <class T>
184struct TypeName<Multiband<T>>
185: public TypeName<T>
186{};
187
188template <class T, int N>
189struct TypeName<TinyVector<T, N>>
190: public TypeName<T>
191{};
192
193template <>
194struct 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
204template <>
205struct 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) \
216template <> \
217struct 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
227VIGRA_SIGNED_INT_NAME(signed char)
228VIGRA_SIGNED_INT_NAME(short)
229VIGRA_SIGNED_INT_NAME(int)
230VIGRA_SIGNED_INT_NAME(long)
231VIGRA_SIGNED_INT_NAME(long long)
232
233#define VIGRA_UNSIGNED_INT_NAME(type) \
234template <> \
235struct 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
245VIGRA_UNSIGNED_INT_NAME(unsigned char)
246VIGRA_UNSIGNED_INT_NAME(unsigned short)
247VIGRA_UNSIGNED_INT_NAME(unsigned int)
248VIGRA_UNSIGNED_INT_NAME(unsigned long)
249VIGRA_UNSIGNED_INT_NAME(unsigned long long)
250
251#define VIGRA_FLOAT_NAME(type) \
252template <> \
253struct 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
263VIGRA_FLOAT_NAME(float)
264VIGRA_FLOAT_NAME(double)
265VIGRA_FLOAT_NAME(long double)
266
267#undef VIGRA_SIGNED_INT_NAME
268#undef VIGRA_UNSIGNED_INT_NAME
269#undef VIGRA_FLOAT_NAME
270
271template <class T = void>
272struct ExportDoc
273{
274 static char const * exec(char const *) { return 0; }
275};
276
277template <>
278struct ExportDoc<void>
279{
280 static char const * exec(char const * h) { return h; }
281};
282
283} // namespace detail
284
285} // namespace vigra
286
287namespace 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) \
295template <class T> \
296struct 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 \
331template <> \
332struct 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 \
343template <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> \
355struct 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) \
472template <class T, int FROM, int TO> \
473struct 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\
504template <class T, int N> \
505struct 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\
542template <int FROM, int TO> \
543struct 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\
554template <int N> \
555struct 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\
566template <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> \
579struct 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
697struct PythonMultidefFunctor {};
698
699template <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>
711struct 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
774template <class Functor>
775inline typename std::enable_if<std::is_base_of<PythonMultidefFunctor, Functor>::value,
776 void>::type
777multidef(char const* python_name, Functor const & f)
778{
779 f.def(python_name);
780}
781
782template <class Functor, class Args>
783inline typename std::enable_if<std::is_base_of<PythonMultidefFunctor, Functor>::value,
784 void>::type
785multidef(char const* python_name, Functor const & f, Args const& args)
786{
787 f.def(python_name, args);
788}
789
790template <class Functor>
791inline typename std::enable_if<std::is_base_of<PythonMultidefFunctor, Functor>::value,
792 void>::type
793multidef(char const* python_name, Functor const & f, const char * help)
794{
795 f.def(python_name, help);
796}
797
798template <class Functor, class Args>
799inline typename std::enable_if<std::is_base_of<PythonMultidefFunctor, Functor>::value,
800 void>::type
801multidef(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
807template <class Functor>
808inline typename std::enable_if<std::is_base_of<PythonMultidefFunctor, Functor>::value,
809 void>::type
810def(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
816template <class Functor, class Args>
817inline typename std::enable_if<std::is_base_of<PythonMultidefFunctor, Functor>::value,
818 void>::type
819def(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
825template <class Functor>
826inline typename std::enable_if<std::is_base_of<PythonMultidefFunctor, Functor>::value,
827 void>::type
828def(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
834template <class Functor, class Args>
835inline typename std::enable_if<std::is_base_of<PythonMultidefFunctor, Functor>::value,
836 void>::type
837def(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.12.2