LSSTApplications  10.0-2-g4f67435,11.0.rc2+1,11.0.rc2+12,11.0.rc2+3,11.0.rc2+4,11.0.rc2+5,11.0.rc2+6,11.0.rc2+7,11.0.rc2+8
LSSTDataManagementBasePackage
PyConverter.h
Go to the documentation of this file.
1 // -*- c++ -*-
2 /*
3  * LSST Data Management System
4  * Copyright 2008, 2009, 2010 LSST Corporation.
5  *
6  * This product includes software developed by the
7  * LSST Project (http://www.lsst.org/).
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the LSST License Statement and
20  * the GNU General Public License along with this program. If not,
21  * see <http://www.lsstcorp.org/LegalNotices/>.
22  */
23 
24 #ifndef NDARRAY_SWIG_PyConverter_h_INCLUDED
25 #define NDARRAY_SWIG_PyConverter_h_INCLUDED
26 
31 #include <Python.h>
32 
33 #include <boost/intrusive_ptr.hpp>
34 #include <complex>
35 
36 #ifndef DOXYGEN
37 //namespace boost {
38 inline void intrusive_ptr_add_ref(PyObject * obj) { Py_INCREF(obj); }
39 inline void intrusive_ptr_release(PyObject * obj) { Py_DECREF(obj); }
40 //}
41 #endif
42 
43 namespace ndarray {
44 
48 typedef boost::intrusive_ptr<PyObject> PyPtr;
49 
50 template <typename T> struct PyConverter;
51 
52 namespace detail {
53 
58 template <typename T>
60 
75  static bool matches(
76  PyObject * arg // input Python object (borrowed)
77  ) {
78  PyPtr p(arg,true);
80  PyErr_Clear();
81  return false;
82  }
83  return true;
84  }
85 
98  static int fromPython(
99  PyObject * arg, // input Python object (borrowed)
100  T * output // pointer to an existing C++
101  ) {
102  PyPtr p(arg,true);
103  if (!PyConverter<T>::fromPythonStage1(p)) return false;
104  return PyConverter<T>::fromPythonStage2(arg,*output);
105  }
106 
107 };
108 
109 } // namespace ndarray::detail
110 
118 template <typename T>
119 struct PyConverter : public detail::PyConverterBase<T> {
120 
127  static PyObject * toPython(
128  T const & input
129  );
130 
135  static PyTypeObject const * getPyType();
136 
145  static bool fromPythonStage1(
146  PyPtr & p
150  );
151 
159  static bool fromPythonStage2(
160  PyPtr const & p,
161  T & output
162  );
163 
164 };
165 
167 
168 template <>
169 struct PyConverter<bool> : public detail::PyConverterBase<bool> {
170 
171  static bool fromPythonStage1(PyPtr & input) {
172  if (!PyBool_Check(input.get())) {
173  PyPtr s(PyObject_Repr(input.get()));
174  if (!s) return false;
175  char * cs = PyString_AsString(s.get());
176  if (!cs) return false;
177  PyErr_Format(PyExc_TypeError,"'%s' is not a valid C++ bool value.",cs);
178  }
179  return true;
180  }
181 
182  static bool fromPythonStage2(PyPtr const & input, bool & output) {
183  NDARRAY_ASSERT(input);
184  output = (input.get() == Py_True);
185  return true;
186  }
187 
188  static PyObject * toPython(bool input) {
189  if (input) Py_RETURN_TRUE;
190  Py_RETURN_FALSE;
191  }
192 
193  static PyTypeObject const * getPyType() { return &PyBool_Type; }
194 };
195 
196 template <>
197 struct PyConverter<int> : public detail::PyConverterBase<int> {
198 
199  static bool fromPythonStage1(PyPtr & input) {
200  if (!PyInt_Check(input.get()) && !PyLong_Check(input.get())) {
201  PyPtr s(PyObject_Repr(input.get()));
202  if (!s) return false;
203  char * cs = PyString_AsString(s.get());
204  if (!cs) return false;
205  PyErr_Format(PyExc_TypeError,"'%s' is not a valid C++ int value.",cs);
206  }
207  return true;
208  }
209 
210  static bool fromPythonStage2(PyPtr const & input, int & output) {
211  NDARRAY_ASSERT(input);
212  output = PyInt_AsLong(input.get());
213  return true;
214  }
215 
216  static PyObject * toPython(int input) {
217  return PyInt_FromLong(input);
218  }
219 
220  static PyTypeObject const * getPyType() { return &PyInt_Type; }
221 };
222 
223 template <>
224 struct PyConverter<long> : public detail::PyConverterBase<long> {
225 
226  static bool fromPythonStage1(PyPtr & input) {
227  if (!PyInt_Check(input.get()) && !PyLong_Check(input.get())) {
228  PyPtr s(PyObject_Repr(input.get()));
229  if (!s) return false;
230  char * cs = PyString_AsString(s.get());
231  if (!cs) return false;
232  PyErr_Format(PyExc_TypeError,"'%s' is not a valid C++ long value.",cs);
233  }
234  return true;
235  }
236 
237  static bool fromPythonStage2(PyPtr const & input, long & output) {
238  NDARRAY_ASSERT(input);
239  output = PyLong_AsLong(input.get());
240  return true;
241  }
242 
243  static PyObject * toPython(long input) {
244  return PyLong_FromLong(input);
245  }
246 
247  static PyTypeObject const * getPyType() { return &PyLong_Type; }
248 };
249 
250 template <>
251 struct PyConverter<float> : public detail::PyConverterBase<float> {
252 
253  static bool fromPythonStage1(PyPtr & input) {
254  if (!PyFloat_Check(input.get())) {
255  PyPtr s(PyObject_Repr(input.get()));
256  if (!s) return false;
257  char * cs = PyString_AsString(s.get());
258  if (!cs) return false;
259  PyErr_Format(PyExc_TypeError,"'%s' is not a valid C++ float value.",cs);
260  }
261  return true;
262  }
263 
264  static bool fromPythonStage2(PyPtr const & input, float & output) {
265  NDARRAY_ASSERT(input);
266  output = PyFloat_AsDouble(input.get());
267  return true;
268  }
269 
270  static PyObject * toPython(float input) {
271  return PyFloat_FromDouble(input);
272  }
273 
274  static PyTypeObject const * getPyType() { return &PyFloat_Type; }
275 };
276 
277 template <>
278 struct PyConverter<double> : public detail::PyConverterBase<double> {
279 
280  static bool fromPythonStage1(PyPtr & input) {
281  if (!PyFloat_Check(input.get())) {
282  PyPtr s(PyObject_Repr(input.get()));
283  if (!s) return false;
284  char * cs = PyString_AsString(s.get());
285  if (!cs) return false;
286  PyErr_Format(PyExc_TypeError,"'%s' is not a valid C++ double value.",cs);
287  }
288  return true;
289  }
290 
291  static bool fromPythonStage2(PyPtr const & input, double & output) {
292  NDARRAY_ASSERT(input);
293  output = PyFloat_AsDouble(input.get());
294  return true;
295  }
296 
297  static PyObject * toPython(double input) {
298  return PyFloat_FromDouble(input);
299  }
300 
301  static PyTypeObject const * getPyType() { return &PyFloat_Type; }
302 };
303 
304 template <typename U>
305 struct PyConverter< std::complex<U> > : public detail::PyConverterBase< std::complex<U> > {
306 
307  static bool fromPythonStage1(PyPtr & input) {
308  if (!PyComplex_Check(input.get())) {
309  PyPtr s(PyObject_Repr(input.get()));
310  if (!s) return false;
311  char * cs = PyString_AsString(s.get());
312  if (!cs) return false;
313  PyErr_Format(PyExc_TypeError,"'%s' is not a valid C++ complex value.",cs);
314  }
315  return true;
316  }
317 
318  static bool fromPythonStage2(PyPtr const & input, std::complex<U> & output) {
319  NDARRAY_ASSERT(input);
320  output.real() = PyComplex_RealAsDouble(input.get());
321  output.imag() = PyComplex_ImagAsDouble(input.get());
322  return true;
323  }
324 
325  static PyObject * toPython(std::complex<U> const & input) {
326  return PyComplex_FromDoubles(input.real(),input.imag());
327  }
328 
329  static PyTypeObject const * getPyType() { return &PyComplex_Type; }
330 };
331 
332 template <>
333 struct PyConverter< std::string > : public detail::PyConverterBase<std::string> {
334 
335  static bool fromPythonStage1(PyPtr & input) {
336  if (!PyString_Check(input.get())) {
337  PyPtr s(PyObject_Repr(input.get()));
338  if (!s) return false;
339  char * cs = PyString_AsString(s.get());
340  if (!cs) return false;
341  PyErr_Format(PyExc_TypeError,"'%s' is not a valid C++ string value.",cs);
342  }
343  return true;
344  }
345 
346  static bool fromPythonStage2(PyPtr const & input, std::string & output) {
347  NDARRAY_ASSERT(input);
348  char * buf = 0;
349  Py_ssize_t size = 0;
350  if (PyString_AsStringAndSize(input.get(),&buf,&size) == -1) return false;
351  output = std::string(buf,size);
352  return true;
353  }
354 
355  static PyObject * toPython(std::string const & input) {
356  return PyString_FromStringAndSize(input.data(),input.size());
357  }
358 
359  static PyTypeObject const * getPyType() { return &PyString_Type; }
360 };
361 
363 
364 } // namespace ndarray
365 
366 #endif // !NDARRAY_SWIG_PyConverter_h_INCLUDED
static int fromPython(PyObject *arg, T *output)
Convert a Python object to a C++ object.
Definition: PyConverter.h:98
static bool fromPythonStage2(PyPtr const &p, T &output)
Complete a Python to C++ conversion begun with fromPythonStage1().
boost::intrusive_ptr< PyObject > PyPtr
A reference-counting smart pointer for PyObject.
Definition: PyConverter.h:48
static PyObject * toPython(T const &input)
Convert a C++ object to a new Python object.
static bool matches(PyObject *arg)
Check if a Python object might be convertible to T.
Definition: PyConverter.h:75
#define NDARRAY_ASSERT(ARG)
Definition: ndarray_fwd.h:51
A class providing Python conversion functions for T.
Definition: PyConverter.h:50
static bool fromPythonStage1(PyPtr &p)
Check if a Python object is convertible to T and optionally begin the conversion by replacing the inp...
static PyTypeObject const * getPyType()
Return the Python TypeObject that corresponds to the object the toPython() function returns...