[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]
vigra/numpy_array_converters.hxx | ![]() |
00001 /************************************************************************/ 00002 /* */ 00003 /* Copyright 2009 by Ullrich Koethe and Hans Meine */ 00004 /* */ 00005 /* This file is part of the VIGRA computer vision library. */ 00006 /* The VIGRA Website is */ 00007 /* http://hci.iwr.uni-heidelberg.de/vigra/ */ 00008 /* Please direct questions, bug reports, and contributions to */ 00009 /* ullrich.koethe@iwr.uni-heidelberg.de or */ 00010 /* vigra@informatik.uni-hamburg.de */ 00011 /* */ 00012 /* Permission is hereby granted, free of charge, to any person */ 00013 /* obtaining a copy of this software and associated documentation */ 00014 /* files (the "Software"), to deal in the Software without */ 00015 /* restriction, including without limitation the rights to use, */ 00016 /* copy, modify, merge, publish, distribute, sublicense, and/or */ 00017 /* sell copies of the Software, and to permit persons to whom the */ 00018 /* Software is furnished to do so, subject to the following */ 00019 /* conditions: */ 00020 /* */ 00021 /* The above copyright notice and this permission notice shall be */ 00022 /* included in all copies or substantial portions of the */ 00023 /* Software. */ 00024 /* */ 00025 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */ 00026 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */ 00027 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */ 00028 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */ 00029 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */ 00030 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ 00031 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ 00032 /* OTHER DEALINGS IN THE SOFTWARE. */ 00033 /* */ 00034 /************************************************************************/ 00035 00036 #ifndef VIGRA_NUMPY_ARRAY_CONVERTERS_HXX 00037 #define VIGRA_NUMPY_ARRAY_CONVERTERS_HXX 00038 00039 #include "numpy_array.hxx" 00040 #include "metaprogramming.hxx" 00041 #include <boost/python.hpp> 00042 #include <boost/python/to_python_converter.hpp> 00043 #include <set> 00044 00045 namespace vigra { 00046 00047 template <class Array> 00048 PyObject * returnNumpyArray(Array const & a) 00049 { 00050 PyObject * pa = a.pyObject(); 00051 if(pa == 0) 00052 PyErr_SetString(PyExc_ValueError, "returnNumpyArray(): Conversion to Python failed, array has no data."); 00053 else 00054 Py_INCREF(pa); 00055 return pa; 00056 } 00057 00058 VIGRA_EXPORT std::set<std::string> & exportedArrayKeys(); 00059 00060 template <class ArrayType> 00061 struct NumpyArrayConverter {}; 00062 00063 template <unsigned int N, class T, class Stride> 00064 struct NumpyArrayConverter<NumpyArray<N, T, Stride> > 00065 { 00066 typedef NumpyArray<N, T, Stride> ArrayType; 00067 typedef typename ArrayType::ArrayTraits ArrayTraits; 00068 00069 NumpyArrayConverter(); 00070 00071 static void* convertible(PyObject* obj); 00072 00073 // from Python 00074 static void construct(PyObject* obj, 00075 boost::python::converter::rvalue_from_python_stage1_data* data); 00076 00077 // to Python 00078 static PyObject* convert(ArrayType const& a) 00079 { 00080 return returnNumpyArray(a); 00081 } 00082 }; 00083 00084 template <unsigned int N, class T, class Stride> 00085 NumpyArrayConverter<NumpyArray<N, T, Stride> >::NumpyArrayConverter() 00086 { 00087 using namespace boost::python; 00088 00089 converter::registration const * reg = converter::registry::query(type_id<ArrayType>()); 00090 00091 // register the to_python_converter only once 00092 // FIXME: I'm not sure if this is correct. 00093 if(!reg || !reg->rvalue_chain) 00094 { 00095 to_python_converter<ArrayType, NumpyArrayConverter>(); 00096 } 00097 converter::registry::insert(&convertible, &construct, type_id<ArrayType>()); 00098 } 00099 00100 template <unsigned int N, class T, class Stride> 00101 void * NumpyArrayConverter<NumpyArray<N, T, Stride> >::convertible(PyObject* obj) 00102 { 00103 bool isCompatible = obj == Py_None || ArrayType::isStrictlyCompatible(obj); 00104 // std::cerr << "compatible for " << typeid(NumpyArray<N, T, Stride>).name() << ": " << isCompatible << "\n"; 00105 return isCompatible 00106 ? obj 00107 : 0; 00108 } 00109 00110 // from Python 00111 template <unsigned int N, class T, class Stride> 00112 void NumpyArrayConverter<NumpyArray<N, T, Stride> >::construct(PyObject* obj, 00113 boost::python::converter::rvalue_from_python_stage1_data* data) 00114 { 00115 void* const storage = 00116 ((boost::python::converter::rvalue_from_python_storage<ArrayType>* ) data)->storage.bytes; 00117 00118 ArrayType * array = new (storage) ArrayType(); 00119 if(obj != Py_None) 00120 array->makeReferenceUnchecked(obj); 00121 00122 data->convertible = storage; 00123 } 00124 00125 template <unsigned int N, class T, class Stride> 00126 struct NumpyArrayConverter<MultiArrayView<N, T, Stride> > 00127 : public NumpyArrayConverter<NumpyArray<N, T, Stride> > 00128 { 00129 typedef NumpyArrayConverter<NumpyArray<N, T, Stride> > BaseType; 00130 typedef MultiArrayView<N, T, Stride> ArrayType; 00131 00132 NumpyArrayConverter() 00133 { 00134 using namespace boost::python; 00135 converter::registry::insert(&BaseType::convertible, &BaseType::construct, 00136 type_id<ArrayType>()); 00137 } 00138 }; 00139 00140 template <class Iter, class End> 00141 struct RegisterNumpyArrayConverters 00142 { 00143 static void exec() 00144 { 00145 typedef typename UnqualifiedType<typename boost::mpl::deref<Iter>::type>::type Type; 00146 NumpyArrayConverter<Type>(); 00147 RegisterNumpyArrayConverters<typename boost::mpl::next<Iter>::type, End>::exec(); 00148 } 00149 }; 00150 00151 template <class End> 00152 struct RegisterNumpyArrayConverters<End, End> 00153 { 00154 static void exec() 00155 {} 00156 }; 00157 00158 template <class Typelist> 00159 void registerNumpyArrayConverters(Typelist) 00160 { 00161 RegisterNumpyArrayConverters<typename boost::mpl::begin<Typelist>::type, 00162 typename boost::mpl::end<Typelist>::type >::exec(); 00163 } 00164 00165 template <class FN> 00166 FN registerConverters(FN f) 00167 { 00168 registerNumpyArrayConverters(boost::python::detail::get_signature(f)); 00169 return f; 00170 } 00171 00172 00173 } // namespace vigra 00174 00175 namespace boost { namespace python { 00176 00177 #define VIGRA_PYTHON_MULTITYPE_FUNCTOR(functor_name, function) \ 00178 template <class T> \ 00179 struct functor_name##Impl \ 00180 { \ 00181 typedef functor_name##Impl type; \ 00182 \ 00183 static void def(const char * pythonName) \ 00184 { \ 00185 boost::python::def(pythonName, vigra::registerConverters(&function<T>)); \ 00186 } \ 00187 \ 00188 template <class A1> \ 00189 static void def(const char * pythonName, A1 const & a1) \ 00190 { \ 00191 boost::python::def(pythonName, vigra::registerConverters(&function<T>), a1); \ 00192 } \ 00193 \ 00194 template <class A1, class A2> \ 00195 static void def(const char * pythonName, A1 const & a1, A2 const & a2) \ 00196 { \ 00197 boost::python::def(pythonName, vigra::registerConverters(&function<T>), a1, a2); \ 00198 } \ 00199 \ 00200 template <class A1, class A2, class A3> \ 00201 static void def(const char * pythonName, A1 const & a1, A2 const & a2, A3 const & a3) \ 00202 { \ 00203 boost::python::def(pythonName, vigra::registerConverters(&function<T>), a1, a2, a3); \ 00204 } \ 00205 }; \ 00206 \ 00207 template <> \ 00208 struct functor_name##Impl<void> \ 00209 { \ 00210 typedef void type; \ 00211 }; \ 00212 \ 00213 template <class T1, \ 00214 class T2 = void, \ 00215 class T3 = void, \ 00216 class T4 = void, \ 00217 class T5 = void, \ 00218 class T6 = void, \ 00219 class T7 = void, \ 00220 class T8 = void, \ 00221 class T9 = void, \ 00222 class T10 = void> \ 00223 struct functor_name \ 00224 : public boost::python::TypeList<typename functor_name##Impl<T1>::type, \ 00225 boost::python::TypeList<typename functor_name##Impl<T2>::type, \ 00226 boost::python::TypeList<typename functor_name##Impl<T3>::type, \ 00227 boost::python::TypeList<typename functor_name##Impl<T4>::type, \ 00228 boost::python::TypeList<typename functor_name##Impl<T5>::type, \ 00229 boost::python::TypeList<typename functor_name##Impl<T6>::type, \ 00230 boost::python::TypeList<typename functor_name##Impl<T7>::type, \ 00231 boost::python::TypeList<typename functor_name##Impl<T8>::type, \ 00232 boost::python::TypeList<typename functor_name##Impl<T9>::type, \ 00233 boost::python::TypeList<typename functor_name##Impl<T10>::type, \ 00234 boost::python::TypeList<void, void> > > > > > > > > > > \ 00235 {}; 00236 00237 template <class Head, class Tail> 00238 struct TypeList 00239 { 00240 typedef Head head; 00241 typedef Tail tail; 00242 }; 00243 00244 // in the sequel, the doc string is only registered with the last 00245 // overload, so that it shows up only once 00246 template <class Head, class Tail> 00247 inline void multidef(char const* functor_name, TypeList<Head, Tail>) 00248 { 00249 Head::def(functor_name); 00250 multidef(functor_name, Tail()); 00251 } 00252 00253 template <class Head, class Tail> 00254 inline void multidef(char const* functor_name, TypeList<Head, Tail>, const char * help) 00255 { 00256 Head::def(functor_name); 00257 multidef(functor_name, Tail(), help); 00258 } 00259 00260 template <class Head, class Tail, class Args> 00261 inline void multidef(char const* functor_name, TypeList<Head, Tail>, Args const& args) 00262 { 00263 Head::def(functor_name, args); 00264 multidef(functor_name, Tail(), args); 00265 } 00266 00267 template <class Head, class Tail, class Args> 00268 inline void multidef(char const* functor_name, TypeList<Head, Tail>, Args const& args, char const * help) 00269 { 00270 Head::def(functor_name, args); 00271 multidef(functor_name, Tail(), args, help); 00272 } 00273 00274 template <class Head, class Tail> 00275 inline void multidef(char const* functor_name, TypeList<Head, TypeList<void, Tail> >) 00276 { 00277 Head::def(functor_name); 00278 } 00279 00280 template <class Head, class Tail, class Args> 00281 inline void multidef(char const* functor_name, TypeList<Head, TypeList<void, Tail> >, Args const& args) 00282 { 00283 Head::def(functor_name, args); 00284 } 00285 00286 template <class Head, class Tail> 00287 inline void multidef(char const* functor_name, TypeList<Head, TypeList<void, Tail> >, const char * help) 00288 { 00289 Head::def(functor_name, help); 00290 } 00291 00292 template <class Head, class Tail, class Args> 00293 inline void multidef(char const* functor_name, TypeList<Head, TypeList<void, Tail> >, Args const& args, const char * help) 00294 { 00295 Head::def(functor_name, args, help); 00296 } 00297 00298 }} // namespace boost::python 00299 00300 #endif // VIGRA_NUMPY_ARRAY_CONVERTERS_HXX
© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) |
html generated using doxygen and Python
|