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

python_utility.hxx
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
45namespace vigra {
46
47/****************************************************************/
48/* */
49/* exception conversion */
50/* */
51/****************************************************************/
52
53inline std::string dataFromPython(PyObject * data, const char * defaultVal);
54
55template <class PYOBJECT_PTR>
56void 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
78class 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
219inline 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
230inline python_ptr pythonFromData(bool t)
231{
232 return python_ptr(PyBool_FromLong(t ? 1 : 0), python_ptr::new_nonzero_reference);
233}
234
235inline 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
244inline 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) \
250inline 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
280inline 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
288inline 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) \
303inline 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
333VIGRA_DATA_FROM_PYTHON(float, PyFloat_Check, PyFloat_AsDouble)
334VIGRA_DATA_FROM_PYTHON(double, PyFloat_Check, PyFloat_AsDouble)
335
336inline 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
349inline 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
362inline 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
377template <class T>
378T 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
390inline std::string
391pythonGetAttr(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
405inline python_ptr
406makePythonDictionary(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
422template <class T, int N>
423python_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
434template <class T>
435python_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
448class 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
Definition array_vector.hxx:77
Class for fixed size vectors.
Definition tinyvector.hxx:1008
NumericTraits< T >::Promote trace(MultiArrayView< 2, T, C > const &m)
Definition matrix.hxx:801

© 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.12.2 (Mon Apr 14 2025)