[ 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 template <class PYOBJECT_PTR>
48 void pythonToCppException(PYOBJECT_PTR obj)
49 {
50  if(obj != 0)
51  return;
52  PyObject * type, * value, * trace;
53  PyErr_Fetch(&type, &value, &trace);
54  if(type == 0)
55  return;
56  std::string message(((PyTypeObject *)type)->tp_name);
57  if(PyString_Check(value))
58  {
59  message += std::string(": ") + PyString_AS_STRING(value);
60  }
61 
62  Py_XDECREF(type);
63  Py_XDECREF(value);
64  Py_XDECREF(trace);
65  throw std::runtime_error(message.c_str());
66 }
67 
68 /********************************************************/
69 /* */
70 /* python_ptr */
71 /* */
72 /********************************************************/
73 
74 class python_ptr
75 {
76  private:
77  PyObject * ptr_;
78 
79  public:
80 
81  typedef PyObject element_type;
82  typedef PyObject value_type;
83  typedef PyObject * pointer;
84  typedef PyObject & reference;
85 
86  enum refcount_policy { increment_count, borrowed_reference = increment_count,
87  keep_count, new_reference = keep_count, new_nonzero_reference };
88 
89  explicit python_ptr(pointer p = 0, refcount_policy rp = increment_count)
90  : ptr_( p )
91  {
92  if(rp == increment_count)
93  {
94  Py_XINCREF(ptr_);
95  }
96  else if(rp == new_nonzero_reference)
97  {
98  pythonToCppException(p);
99  }
100  }
101 
102  python_ptr(python_ptr const & p)
103  : ptr_(p.ptr_)
104  {
105  Py_XINCREF(ptr_);
106  }
107 
108  python_ptr & operator=(pointer p)
109  {
110  reset(p);
111  return *this;
112  }
113 
114  python_ptr & operator=(python_ptr const & r)
115  {
116  reset(r.ptr_);
117  return *this;
118  }
119 
120  ~python_ptr()
121  {
122  reset();
123  }
124 
125  void reset(pointer p = 0, refcount_policy rp = increment_count)
126  {
127  if(p == ptr_)
128  return;
129  if(rp == increment_count)
130  {
131  Py_XINCREF(p);
132  }
133  else if(rp == new_nonzero_reference)
134  {
135  pythonToCppException(p);
136  }
137  Py_XDECREF(ptr_);
138  ptr_ = p;
139  }
140 
141  pointer release(bool return_borrowed_reference = false)
142  {
143  pointer p = ptr_;
144  ptr_ = 0;
145  if(return_borrowed_reference)
146  {
147  Py_XDECREF(p);
148  }
149  return p;
150  }
151 
152  reference operator* () const
153  {
154  vigra_precondition(ptr_ != 0, "python_ptr::operator*(): Cannot dereference NULL pointer.");
155  return *ptr_;
156  }
157 
158  pointer operator-> () const
159  {
160  vigra_precondition(ptr_ != 0, "python_ptr::operator->(): Cannot dereference NULL pointer.");
161  return ptr_;
162  }
163 
164  pointer ptr() const
165  {
166  return ptr_;
167  }
168 
169  pointer get() const
170  {
171  return ptr_;
172  }
173 
174  operator pointer() const
175  {
176  return ptr_;
177  }
178 
179  bool operator! () const
180  {
181  return ptr_ == 0;
182  }
183 
184  bool unique() const
185  {
186  return ptr_ && ptr_->ob_refcnt == 1;
187  }
188 
189  void swap(python_ptr & other)
190  {
191  std::swap(ptr_, other.ptr_);
192  }
193 
194  bool operator==(python_ptr const & p) const
195  {
196  return ptr_ == p.ptr_;
197  }
198 
199  bool operator==(pointer p) const
200  {
201  return ptr_ == p;
202  }
203 
204  bool operator!=(python_ptr const & p) const
205  {
206  return ptr_ != p.ptr_;
207  }
208 
209  bool operator!=(pointer p) const
210  {
211  return ptr_ != p;
212  }
213 };
214 
215 inline void swap(python_ptr & a, python_ptr & b)
216 {
217  a.swap(b);
218 }
219 
220 /****************************************************************/
221 
222 inline python_ptr
223 makePythonDictionary(char const * k1 = 0, PyObject * a1 = 0,
224  char const * k2 = 0, PyObject * a2 = 0,
225  char const * k3 = 0, PyObject * a3 = 0)
226 {
227  python_ptr dict(PyDict_New(), python_ptr::keep_count);
228  pythonToCppException(dict);
229  if(k1 && a1)
230  PyDict_SetItemString(dict, k1, a1);
231  if(k2 && a2)
232  PyDict_SetItemString(dict, k2, a2);
233  if(k3 && a3)
234  PyDict_SetItemString(dict, k3, a3);
235  return dict;
236 }
237 
238 /****************************************************************/
239 
240 inline python_ptr pythonFromData(bool t)
241 {
242  python_ptr res(PyBool_FromLong(t ? 1 : 0), python_ptr::keep_count);
243  pythonToCppException(res);
244  return res;
245 }
246 
247 inline python_ptr pythonFromData(std::string const & s)
248 {
249  python_ptr res(PyString_FromString(s.c_str()), python_ptr::keep_count);
250  pythonToCppException(res);
251  return res;
252 }
253 
254 inline python_ptr pythonFromData(long long t)
255 {
256  python_ptr res;
257  if(t > (long long)NumericTraits<long>::max() || t < (long long)NumericTraits<long>::min())
258  res = python_ptr(PyLong_FromLongLong(t), python_ptr::keep_count);
259  else
260  res = python_ptr(PyInt_FromLong((long)t), python_ptr::keep_count);
261  pythonToCppException(res);
262  return res;
263 }
264 
265 inline python_ptr pythonFromData(unsigned long long t)
266 {
267  python_ptr res;
268  if(t > (unsigned long long)NumericTraits<long>::max())
269  res = python_ptr(PyLong_FromUnsignedLongLong(t), python_ptr::keep_count);
270  else
271  res = python_ptr(PyInt_FromLong((long)t), python_ptr::keep_count);
272  pythonToCppException(res);
273  return res;
274 }
275 
276 #define VIGRA_PYTHON_FROM_DATA(type, fct, cast_type) \
277 inline python_ptr pythonFromData(type t) \
278 { \
279  python_ptr res(fct((cast_type)t), python_ptr::keep_count); \
280  pythonToCppException(res); \
281  return res; \
282 }
283 
284 VIGRA_PYTHON_FROM_DATA(signed char, PyInt_FromLong, long)
285 VIGRA_PYTHON_FROM_DATA(unsigned char, PyInt_FromLong, long)
286 VIGRA_PYTHON_FROM_DATA(short, PyInt_FromLong, long)
287 VIGRA_PYTHON_FROM_DATA(unsigned short, PyInt_FromLong, long)
288 VIGRA_PYTHON_FROM_DATA(long, PyInt_FromLong, long)
289 VIGRA_PYTHON_FROM_DATA(unsigned long, PyInt_FromSize_t, size_t)
290 VIGRA_PYTHON_FROM_DATA(int, PyInt_FromSsize_t, Py_ssize_t)
291 VIGRA_PYTHON_FROM_DATA(unsigned int, PyInt_FromSize_t, size_t)
292 VIGRA_PYTHON_FROM_DATA(float, PyFloat_FromDouble, double)
293 VIGRA_PYTHON_FROM_DATA(double, PyFloat_FromDouble, double)
294 VIGRA_PYTHON_FROM_DATA(char const *, PyString_FromString, char const *)
295 
296 #undef VIGRA_PYTHON_FROM_DATA
297 
298 /****************************************************************/
299 
300 #define VIGRA_DATA_FROM_PYTHON(type, check, extract) \
301 inline type dataFromPython(PyObject * data, type const & defaultVal) \
302 { \
303  return data && check(data) \
304  ? (type)extract(data) \
305  : defaultVal; \
306 }
307 
308 VIGRA_DATA_FROM_PYTHON(signed char, PyInt_Check, PyInt_AsLong)
309 VIGRA_DATA_FROM_PYTHON(unsigned char, PyInt_Check, PyInt_AsLong)
310 VIGRA_DATA_FROM_PYTHON(short, PyInt_Check, PyInt_AsLong)
311 VIGRA_DATA_FROM_PYTHON(unsigned short, PyInt_Check, PyInt_AsLong)
312 VIGRA_DATA_FROM_PYTHON(long, PyInt_Check, PyInt_AsLong)
313 VIGRA_DATA_FROM_PYTHON(unsigned long, PyInt_Check, PyInt_AsUnsignedLongMask)
314 VIGRA_DATA_FROM_PYTHON(int, PyInt_Check, PyInt_AsLong)
315 VIGRA_DATA_FROM_PYTHON(unsigned int, PyInt_Check, PyInt_AsUnsignedLongMask)
316 VIGRA_DATA_FROM_PYTHON(long long, PyInt_Check, PyInt_AsSsize_t)
317 VIGRA_DATA_FROM_PYTHON(unsigned long long, PyInt_Check, PyInt_AsUnsignedLongLongMask)
318 VIGRA_DATA_FROM_PYTHON(float, PyFloat_Check, PyFloat_AsDouble)
319 VIGRA_DATA_FROM_PYTHON(double, PyFloat_Check, PyFloat_AsDouble)
320 
321 inline std::string dataFromPython(PyObject * data, const char * defaultVal)
322 {
323  return data && PyString_Check(data)
324  ? std::string(PyString_AsString(data))
325  : std::string(defaultVal);
326 }
327 
328 inline std::string dataFromPython(PyObject * data, std::string const & defaultVal)
329 {
330  return data && PyString_Check(data)
331  ? std::string(PyString_AsString(data))
332  : defaultVal;
333 }
334 
335 inline python_ptr dataFromPython(PyObject * data, python_ptr defaultVal)
336 {
337  return data
338  ? python_ptr(data)
339  : defaultVal;
340 }
341 
342 #undef VIGRA_DATA_FROM_PYTHON
343 
344 /****************************************************************/
345 
346 template <class T>
347 T pythonGetAttr(PyObject * obj, const char * key, T defaultValue)
348 {
349  if(!obj)
350  return defaultValue;
351 
352  python_ptr k(PyString_FromString(key), python_ptr::keep_count);
353  pythonToCppException(k);
354  python_ptr pres(PyObject_GetAttr(obj, k), python_ptr::keep_count);
355  if(!pres)
356  PyErr_Clear();
357  return dataFromPython(pres, defaultValue);
358 }
359 
360 inline std::string
361 pythonGetAttr(PyObject * obj, const char * key, const char * defaultValue)
362 {
363  if(!obj)
364  return std::string(defaultValue);
365 
366  python_ptr k(PyString_FromString(key), python_ptr::keep_count);
367  pythonToCppException(k);
368  python_ptr pres(PyObject_GetAttr(obj, k), python_ptr::keep_count);
369  if(!pres)
370  PyErr_Clear();
371  return dataFromPython(pres, defaultValue);
372 }
373 
374 /****************************************************************/
375 
376 template <class T, int N>
377 python_ptr shapeToPythonTuple(TinyVector<T, N> const & shape)
378 {
379  python_ptr tuple(PyTuple_New(N), python_ptr::keep_count);
380  pythonToCppException(tuple);
381  for(unsigned int k=0; k<N; ++k)
382  {
383  PyTuple_SET_ITEM((PyTupleObject *)tuple.get(), k, pythonFromData(shape[k]).release());
384  }
385  return tuple;
386 }
387 
388 template <class T>
389 python_ptr shapeToPythonTuple(ArrayVectorView<T> const & shape)
390 {
391  python_ptr tuple(PyTuple_New(shape.size()), python_ptr::keep_count);
392  pythonToCppException(tuple);
393  for(unsigned int k=0; k<shape.size(); ++k)
394  {
395  PyTuple_SET_ITEM((PyTupleObject *)tuple.get(), k, pythonFromData(shape[k]).release());
396  }
397  return tuple;
398 }
399 
400 /****************************************************************/
401 
402 class PyAllowThreads
403 {
404  PyThreadState * save_;
405 
406  // make it non-copyable
407  PyAllowThreads(PyAllowThreads const &);
408  PyAllowThreads & operator=(PyAllowThreads const &);
409 
410  public:
411  PyAllowThreads()
412  : save_(PyEval_SaveThread())
413  {}
414 
415  ~PyAllowThreads()
416  {
417  PyEval_RestoreThread(save_);
418  }
419 };
420 
421 } // namespace vigra
422 
423 #endif // VIGRA_PYTHON_UTILITY_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.10.0 (Thu Jan 8 2015)