[ 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 <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) Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany | html generated using doxygen and Python vigra 1.7.1 (3 Dec 2010)