[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]
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 <vigra/numpy_array.hxx> 00040 #include <vigra/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 if(exportedArrayKeys().find(ArrayTraits::typeKeyFull()) == exportedArrayKeys().end()) 00090 { 00091 exportedArrayKeys().insert(ArrayTraits::typeKey()); 00092 exportedArrayKeys().insert(ArrayTraits::typeKeyFull()); 00093 00094 to_python_converter<ArrayType, NumpyArrayConverter>(); 00095 00096 converter::registry::insert(&convertible, &construct, type_id<ArrayType>()); 00097 } 00098 } 00099 00100 template <unsigned int N, class T, class Stride> 00101 void * NumpyArrayConverter<NumpyArray<N, T, Stride> >::convertible(PyObject* obj) 00102 { 00103 return obj == Py_None || ArrayType::isStrictlyCompatible(obj) 00104 ? obj 00105 : 0; 00106 } 00107 00108 // from Python 00109 template <unsigned int N, class T, class Stride> 00110 void NumpyArrayConverter<NumpyArray<N, T, Stride> >::construct(PyObject* obj, 00111 boost::python::converter::rvalue_from_python_stage1_data* data) 00112 { 00113 void* const storage = 00114 ((boost::python::converter::rvalue_from_python_storage<ArrayType>* ) data)->storage.bytes; 00115 00116 ArrayType * array = new (storage) ArrayType(); 00117 if(obj != Py_None) 00118 array->makeReferenceUnchecked(obj); 00119 00120 data->convertible = storage; 00121 } 00122 00123 template <unsigned int N, class T, class Stride> 00124 struct NumpyArrayConverter<MultiArrayView<N, T, Stride> > 00125 : public NumpyArrayConverter<NumpyArray<N, T, Stride> > 00126 { 00127 typedef NumpyArrayConverter<NumpyArray<N, T, Stride> > BaseType; 00128 typedef MultiArrayView<N, T, Stride> ArrayType; 00129 00130 NumpyArrayConverter() 00131 { 00132 using namespace boost::python; 00133 converter::registry::insert(&BaseType::convertible, &BaseType::construct, 00134 type_id<ArrayType>()); 00135 } 00136 }; 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 template <class Head, class Tail> 00245 inline void multidef(char const* functor_name, TypeList<Head, Tail>) 00246 { 00247 Head::def(functor_name); 00248 multidef(functor_name, Tail()); 00249 } 00250 00251 template <class Head, class Tail> 00252 inline void multidef(char const* functor_name, TypeList<Head, Tail>, const char * help) 00253 { 00254 Head::def(functor_name, help); 00255 multidef(functor_name, Tail()); 00256 } 00257 00258 template <class Head, class Tail, class Args> 00259 inline void multidef(char const* functor_name, TypeList<Head, Tail>, Args const& args) 00260 { 00261 Head::def(functor_name, args); 00262 multidef(functor_name, Tail(), args); 00263 } 00264 00265 template <class Head, class Tail, class Args> 00266 inline void multidef(char const* functor_name, TypeList<Head, Tail>, Args const& args, char const * help) 00267 { 00268 Head::def(functor_name, args, help); 00269 multidef(functor_name, Tail(), args); 00270 } 00271 00272 template <class Head, class Tail> 00273 inline void multidef(char const* functor_name, TypeList<Head, TypeList<void, Tail> >) 00274 { 00275 Head::def(functor_name); 00276 } 00277 00278 template <class Head, class Tail, class Args> 00279 inline void multidef(char const* functor_name, TypeList<Head, TypeList<void, Tail> >, Args const& args) 00280 { 00281 Head::def(functor_name, args); 00282 } 00283 00284 template <class Head, class Tail> 00285 inline void multidef(char const* functor_name, TypeList<Head, TypeList<void, Tail> >, const char * help) 00286 { 00287 Head::def(functor_name, help); 00288 } 00289 00290 template <class Head, class Tail, class Args> 00291 inline void multidef(char const* functor_name, TypeList<Head, TypeList<void, Tail> >, Args const& args, const char * help) 00292 { 00293 Head::def(functor_name, args, help); 00294 } 00295 00296 }} // namespace boost::python 00297 00298 #endif // VIGRA_NUMPY_ARRAY_CONVERTERS_HXX
© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) |
html generated using doxygen and Python
|