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

vigra/numpy_array_converters.hxx VIGRA

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)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.8.0 (20 Sep 2011)