[ 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) Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany | html generated using doxygen and Python vigra 1.9.0 (Tue Nov 6 2012)