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

python_utility.hxx VIGRA

1 /************************************************************************/
2 /* */
3 /* Copyright 2009 by Ullrich Koethe and Hans Meine */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35 
36 #ifndef VIGRA_PYTHON_UTILITY_HXX
37 #define VIGRA_PYTHON_UTILITY_HXX
38 
39 #include <Python.h>
40 #include <algorithm>
41 #include <string>
42 #include "vigra/error.hxx"
43 #include "vigra/tinyvector.hxx"
44 
45 namespace vigra {
46 
47 /****************************************************************/
48 /* */
49 /* exception conversion */
50 /* */
51 /****************************************************************/
52 
53 inline std::string dataFromPython(PyObject * data, const char * defaultVal);
54 
55 template <class PYOBJECT_PTR>
56 void pythonToCppException(PYOBJECT_PTR obj)
57 {
58  if(obj != 0)
59  return;
60  PyObject * type, * value, * trace;
61  PyErr_Fetch(&type, &value, &trace);
62  if(type == 0)
63  return;
64  std::string message(((PyTypeObject *)type)->tp_name);
65  message += ": " + dataFromPython(value, "<no error message>");
66  Py_XDECREF(type);
67  Py_XDECREF(value);
68  Py_XDECREF(trace);
69  throw std::runtime_error(message.c_str());
70 }
71 
72 /********************************************************/
73 /* */
74 /* python_ptr */
75 /* */
76 /********************************************************/
77 
78 class python_ptr
79 {
80  private:
81  PyObject * ptr_;
82 
83  public:
84 
85  typedef PyObject element_type;
86  typedef PyObject value_type;
87  typedef PyObject * pointer;
88  typedef PyObject & reference;
89 
90  enum refcount_policy { increment_count, borrowed_reference = increment_count,
91  keep_count, new_reference = keep_count, new_nonzero_reference };
92 
93  explicit python_ptr(pointer p = 0, refcount_policy rp = increment_count)
94  : ptr_( p )
95  {
96  if(rp == increment_count)
97  {
98  Py_XINCREF(ptr_);
99  }
100  else if(rp == new_nonzero_reference)
101  {
102  pythonToCppException(p);
103  }
104  }
105 
106  python_ptr(python_ptr const & p)
107  : ptr_(p.ptr_)
108  {
109  Py_XINCREF(ptr_);
110  }
111 
112  python_ptr & operator=(pointer p)
113  {
114  reset(p);
115  return *this;
116  }
117 
118  python_ptr & operator=(python_ptr const & r)
119  {
120  reset(r.ptr_);
121  return *this;
122  }
123 
124  ~python_ptr()
125  {
126  reset();
127  }
128 
129  void reset(pointer p = 0, refcount_policy rp = increment_count)
130  {
131  if(p == ptr_)
132  return;
133  if(rp == increment_count)
134  {
135  Py_XINCREF(p);
136  }
137  else if(rp == new_nonzero_reference)
138  {
139  pythonToCppException(p);
140  }
141  Py_XDECREF(ptr_);
142  ptr_ = p;
143  }
144 
145  pointer release(bool return_borrowed_reference = false)
146  {
147  pointer p = ptr_;
148  ptr_ = 0;
149  if(return_borrowed_reference)
150  {
151  Py_XDECREF(p);
152  }
153  return p;
154  }
155 
156  reference operator* () const
157  {
158  vigra_precondition(ptr_ != 0, "python_ptr::operator*(): Cannot dereference NULL pointer.");
159  return *ptr_;
160  }
161 
162  pointer operator-> () const
163  {
164  vigra_precondition(ptr_ != 0, "python_ptr::operator->(): Cannot dereference NULL pointer.");
165  return ptr_;
166  }
167 
168  pointer ptr() const
169  {
170  return ptr_;
171  }
172 
173  pointer get() const
174  {
175  return ptr_;
176  }
177 
178  operator pointer() const
179  {
180  return ptr_;
181  }
182 
183  bool operator! () const
184  {
185  return ptr_ == 0;
186  }
187 
188  bool unique() const
189  {
190  return ptr_ && ptr_->ob_refcnt == 1;
191  }
192 
193  void swap(python_ptr & other)
194  {
195  std::swap(ptr_, other.ptr_);
196  }
197 
198  bool operator==(python_ptr const & p) const
199  {
200  return ptr_ == p.ptr_;
201  }
202 
203  bool operator==(pointer p) const
204  {
205  return ptr_ == p;
206  }
207 
208  bool operator!=(python_ptr const & p) const
209  {
210  return ptr_ != p.ptr_;
211  }
212 
213  bool operator!=(pointer p) const
214  {
215  return ptr_ != p;
216  }
217 };
218 
219 inline void swap(python_ptr & a, python_ptr & b)
220 {
221  a.swap(b);
222 }
223 
224 /****************************************************************/
225 /* */
226 /* data conversion to python */
227 /* */
228 /****************************************************************/
229 
230 inline python_ptr pythonFromData(bool t)
231 {
232  return python_ptr(PyBool_FromLong(t ? 1 : 0), python_ptr::new_nonzero_reference);
233 }
234 
235 inline python_ptr pythonFromData(char const * str)
236 {
237 #if PY_MAJOR_VERSION < 3
238  return python_ptr(PyString_FromString(str), python_ptr::new_nonzero_reference);
239 #else
240  return python_ptr(PyUnicode_FromString(str), python_ptr::new_nonzero_reference);
241 #endif
242 }
243 
244 inline python_ptr pythonFromData(std::string const & str)
245 {
246  return pythonFromData(str.c_str());
247 }
248 
249 #define VIGRA_PYTHON_FROM_DATA(type, fct, cast_type) \
250 inline python_ptr pythonFromData(type t) \
251 { \
252  return python_ptr(fct((cast_type)t), python_ptr::new_nonzero_reference); \
253 }
254 
255 #if PY_MAJOR_VERSION < 3
256  VIGRA_PYTHON_FROM_DATA(signed char, PyInt_FromLong, long)
257  VIGRA_PYTHON_FROM_DATA(unsigned char, PyInt_FromLong, long)
258  VIGRA_PYTHON_FROM_DATA(short, PyInt_FromLong, long)
259  VIGRA_PYTHON_FROM_DATA(unsigned short, PyInt_FromLong, long)
260  VIGRA_PYTHON_FROM_DATA(long, PyInt_FromLong, long)
261  VIGRA_PYTHON_FROM_DATA(unsigned long, PyInt_FromSize_t, size_t)
262  VIGRA_PYTHON_FROM_DATA(int, PyInt_FromSsize_t, Py_ssize_t)
263  VIGRA_PYTHON_FROM_DATA(unsigned int, PyInt_FromSize_t, size_t)
264  VIGRA_PYTHON_FROM_DATA(float, PyFloat_FromDouble, double)
265  VIGRA_PYTHON_FROM_DATA(double, PyFloat_FromDouble, double)
266 #else
267  VIGRA_PYTHON_FROM_DATA(signed char, PyLong_FromLong, long)
268  VIGRA_PYTHON_FROM_DATA(unsigned char, PyLong_FromLong, long)
269  VIGRA_PYTHON_FROM_DATA(short, PyLong_FromLong, long)
270  VIGRA_PYTHON_FROM_DATA(unsigned short, PyLong_FromLong, long)
271  VIGRA_PYTHON_FROM_DATA(long, PyLong_FromLong, long)
272  VIGRA_PYTHON_FROM_DATA(unsigned long, PyLong_FromSize_t, size_t)
273  VIGRA_PYTHON_FROM_DATA(int, PyLong_FromSsize_t, Py_ssize_t)
274  VIGRA_PYTHON_FROM_DATA(unsigned int, PyLong_FromSize_t, size_t)
275  VIGRA_PYTHON_FROM_DATA(float, PyFloat_FromDouble, double)
276  VIGRA_PYTHON_FROM_DATA(double, PyFloat_FromDouble, double)
277 #endif
278 #undef VIGRA_PYTHON_FROM_DATA
279 
280 inline python_ptr pythonFromData(long long t)
281 {
282  if(t > (long long)NumericTraits<long>::max() || t < (long long)NumericTraits<long>::min())
283  return python_ptr(PyLong_FromLongLong(t), python_ptr::new_nonzero_reference);
284  else
285  return pythonFromData((long)t);
286 }
287 
288 inline python_ptr pythonFromData(unsigned long long t)
289 {
290  if(t > (unsigned long long)NumericTraits<long>::max())
291  return python_ptr(PyLong_FromUnsignedLongLong(t), python_ptr::new_nonzero_reference);
292  else
293  return pythonFromData((long)t);
294 }
295 
296 /****************************************************************/
297 /* */
298 /* data conversion from python */
299 /* */
300 /****************************************************************/
301 
302 #define VIGRA_DATA_FROM_PYTHON(type, check, extract) \
303 inline type dataFromPython(PyObject * data, type const & defaultVal) \
304 { \
305  return data && check(data) \
306  ? (type)extract(data) \
307  : defaultVal; \
308 }
309 
310 #if PY_MAJOR_VERSION < 3
311  VIGRA_DATA_FROM_PYTHON(signed char, PyInt_Check, PyInt_AsLong)
312  VIGRA_DATA_FROM_PYTHON(unsigned char, PyInt_Check, PyInt_AsLong)
313  VIGRA_DATA_FROM_PYTHON(short, PyInt_Check, PyInt_AsLong)
314  VIGRA_DATA_FROM_PYTHON(unsigned short, PyInt_Check, PyInt_AsLong)
315  VIGRA_DATA_FROM_PYTHON(long, PyInt_Check, PyInt_AsLong)
316  VIGRA_DATA_FROM_PYTHON(unsigned long, PyInt_Check, PyInt_AsUnsignedLongMask)
317  VIGRA_DATA_FROM_PYTHON(int, PyInt_Check, PyInt_AsLong)
318  VIGRA_DATA_FROM_PYTHON(unsigned int, PyInt_Check, PyInt_AsUnsignedLongMask)
319  VIGRA_DATA_FROM_PYTHON(long long, PyInt_Check, PyInt_AsSsize_t)
320  VIGRA_DATA_FROM_PYTHON(unsigned long long, PyInt_Check, PyInt_AsUnsignedLongLongMask)
321 #else
322  VIGRA_DATA_FROM_PYTHON(signed char, PyLong_Check, PyLong_AsLong)
323  VIGRA_DATA_FROM_PYTHON(unsigned char, PyLong_Check, PyLong_AsLong)
324  VIGRA_DATA_FROM_PYTHON(short, PyLong_Check, PyLong_AsLong)
325  VIGRA_DATA_FROM_PYTHON(unsigned short, PyLong_Check, PyLong_AsLong)
326  VIGRA_DATA_FROM_PYTHON(long, PyLong_Check, PyLong_AsLong)
327  VIGRA_DATA_FROM_PYTHON(unsigned long, PyLong_Check, PyLong_AsUnsignedLongMask)
328  VIGRA_DATA_FROM_PYTHON(int, PyLong_Check, PyLong_AsLong)
329  VIGRA_DATA_FROM_PYTHON(unsigned int, PyLong_Check, PyLong_AsUnsignedLongMask)
330  VIGRA_DATA_FROM_PYTHON(long long, PyLong_Check, PyLong_AsSsize_t)
331  VIGRA_DATA_FROM_PYTHON(unsigned long long, PyLong_Check, PyLong_AsUnsignedLongLongMask)
332 #endif
333 VIGRA_DATA_FROM_PYTHON(float, PyFloat_Check, PyFloat_AsDouble)
334 VIGRA_DATA_FROM_PYTHON(double, PyFloat_Check, PyFloat_AsDouble)
335 
336 inline std::string dataFromPython(PyObject * data, const char * defaultVal)
337 {
338 #if PY_MAJOR_VERSION < 3
339  return data && PyString_Check(data)
340  ? std::string(PyString_AsString(data))
341 #else
342  python_ptr ascii(PyUnicode_AsASCIIString(data), python_ptr::keep_count);
343  return data && PyBytes_Check(ascii)
344  ? std::string(PyBytes_AsString(ascii))
345 #endif
346  : std::string(defaultVal);
347 }
348 
349 inline std::string dataFromPython(PyObject * data, std::string const & defaultVal)
350 {
351 #if PY_MAJOR_VERSION < 3
352  return data && PyString_Check(data)
353  ? std::string(PyString_AsString(data))
354 #else
355  python_ptr ascii(PyUnicode_AsASCIIString(data), python_ptr::keep_count);
356  return data && PyBytes_Check(ascii)
357  ? std::string(PyBytes_AsString(ascii))
358 #endif
359  : defaultVal;
360 }
361 
362 inline python_ptr dataFromPython(PyObject * data, python_ptr defaultVal)
363 {
364  return data
365  ? python_ptr(data)
366  : defaultVal;
367 }
368 
369 #undef VIGRA_DATA_FROM_PYTHON
370 
371 /****************************************************************/
372 /* */
373 /* access utilities and factory functions */
374 /* */
375 /****************************************************************/
376 
377 template <class T>
378 T pythonGetAttr(PyObject * obj, const char * key, T defaultValue)
379 {
380  if(!obj)
381  return defaultValue;
382  python_ptr k(pythonFromData(key));
383  pythonToCppException(k);
384  python_ptr pres(PyObject_GetAttr(obj, k), python_ptr::keep_count);
385  if(!pres)
386  PyErr_Clear();
387  return dataFromPython(pres, defaultValue);
388 }
389 
390 inline std::string
391 pythonGetAttr(PyObject * obj, const char * key, const char * defaultValue)
392 {
393  if(!obj)
394  return std::string(defaultValue);
395  python_ptr k(pythonFromData(key));
396  pythonToCppException(k);
397  python_ptr pres(PyObject_GetAttr(obj, k), python_ptr::keep_count);
398  if(!pres)
399  PyErr_Clear();
400  return dataFromPython(pres, defaultValue);
401 }
402 
403 /****************************************************************/
404 
405 inline python_ptr
406 makePythonDictionary(char const * k1 = 0, PyObject * a1 = 0,
407  char const * k2 = 0, PyObject * a2 = 0,
408  char const * k3 = 0, PyObject * a3 = 0)
409 {
410  python_ptr dict(PyDict_New(), python_ptr::new_nonzero_reference);
411  if(k1 && a1)
412  PyDict_SetItemString(dict, k1, a1);
413  if(k2 && a2)
414  PyDict_SetItemString(dict, k2, a2);
415  if(k3 && a3)
416  PyDict_SetItemString(dict, k3, a3);
417  return dict;
418 }
419 
420 /****************************************************************/
421 
422 template <class T, int N>
423 python_ptr shapeToPythonTuple(TinyVector<T, N> const & shape)
424 {
425  python_ptr tuple(PyTuple_New(N), python_ptr::keep_count);
426  pythonToCppException(tuple);
427  for(unsigned int k=0; k<N; ++k)
428  {
429  PyTuple_SET_ITEM((PyTupleObject *)tuple.get(), k, pythonFromData(shape[k]).release());
430  }
431  return tuple;
432 }
433 
434 template <class T>
435 python_ptr shapeToPythonTuple(ArrayVectorView<T> const & shape)
436 {
437  python_ptr tuple(PyTuple_New(shape.size()), python_ptr::keep_count);
438  pythonToCppException(tuple);
439  for(unsigned int k=0; k<shape.size(); ++k)
440  {
441  PyTuple_SET_ITEM((PyTupleObject *)tuple.get(), k, pythonFromData(shape[k]).release());
442  }
443  return tuple;
444 }
445 
446 /****************************************************************/
447 
448 class PyAllowThreads
449 {
450  PyThreadState * save_;
451 
452  // make it non-copyable
453  PyAllowThreads(PyAllowThreads const &);
454  PyAllowThreads & operator=(PyAllowThreads const &);
455 
456  public:
457  PyAllowThreads()
458  : save_(PyEval_SaveThread())
459  {}
460 
461  ~PyAllowThreads()
462  {
463  PyEval_RestoreThread(save_);
464  }
465 };
466 
467 } // namespace vigra
468 
469 #endif // VIGRA_PYTHON_UTILITY_HXX
NumericTraits< T >::Promote trace(MultiArrayView< 2, T, C > const &m)
Definition: matrix.hxx:801
bool operator!=(FFTWComplex< R > const &a, const FFTWComplex< R > &b)
not equal
Definition: fftw3.hxx:841
bool operator==(FFTWComplex< R > const &a, const FFTWComplex< R > &b)
equal
Definition: fftw3.hxx:825

© 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.11.1 (Fri May 19 2017)