vigra - vigra/python_utility.hxx Source File

[ 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
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)