1 // Copyright (C) 2019 EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 #ifndef PY2CPP_TYPECONVERSIONS_HXX
20 #define PY2CPP_TYPECONVERSIONS_HXX
34 * toPy functions return a new python object built from a c++ object.
35 * The conversion is always possible and it does not throw exceptions.
38 PyObject * toPy(unsigned int);
39 PyObject * toPy(bool);
40 PyObject * toPy(double);
41 PyObject * toPy(const std::string&);
42 PyObject * toPy(const char*);
43 PyObject * toPy(PyObject *);
44 PyObject * toPy(const PyPtr&);
46 PyObject * toPy(const std::vector<T>& values);
48 PyObject * toPy(const std::list<T>& values);
49 template <class K, class V>
50 PyObject * toPy(const std::map<K, V>& values);
52 PyObject * toPy(const std::tuple<Ts...>& vars );
55 * fromPy functions convert a python object to a c++ object.
56 * If the convertion fails, the ConversionCheck object returned contains the
57 * error message. No exception is thrown.
59 ConversionCheck fromPy( PyObject *, int&);
60 ConversionCheck fromPy( PyObject *, unsigned int&);
61 ConversionCheck fromPy( PyObject *, bool&);
62 ConversionCheck fromPy( PyObject *, double&);
63 ConversionCheck fromPy( PyObject *, std::string&);
64 ConversionCheck fromPy( PyObject *, PyObject *&);
65 ConversionCheck fromPy( PyObject *, PyPtr&);
67 ConversionCheck fromPy(PyObject * obj, std::tuple<Ts&...>& vars);
69 ConversionCheck fromPy( PyObject *obj, std::vector<T>& result);
71 ConversionCheck fromPy( PyObject *obj, std::list<T>& result);
72 template <class K, class V>
73 ConversionCheck fromPy( PyObject *obj, std::map<K, V>& result);
75 /*! This templated version of fromPy throws ConversionException if the
79 T fromPy( PyObject *po);
81 // These versions of fromPy and toPy use PyPtr instead of PyObject *
83 T fromPyPtr( const PyPtr& py);
85 ConversionCheck fromPyPtr( const PyPtr& py, T& var);
87 PyPtr toPyPtr(const T& v);
89 PyPtr fromPy<PyPtr>( PyObject *po);
91 ////////////////////////////////////////////////////////////////////////////////
92 // Template implementations
93 ////////////////////////////////////////////////////////////////////////////////
96 template<std::size_t I = 0, class ...Ts>
97 inline typename std::enable_if<I == sizeof...(Ts), void>::type
98 addInPyTuple(PyObject * result, const std::tuple<Ts...>& vars )
102 template<std::size_t I = 0, class ...Ts>
103 inline typename std::enable_if<I < sizeof...(Ts), void>::type
104 addInPyTuple(PyObject * result, const std::tuple<Ts...>& vars )
106 PyObject * obj = toPy(std::get<I>(vars));
107 PyTuple_SetItem(result, I, obj);
108 addInPyTuple<I+1, Ts... >(result, vars);
111 template<class ...Ts>
112 PyObject * toPy(const std::tuple<Ts...>& vars )
114 PyObject * result = PyTuple_New(sizeof...(Ts));
115 addInPyTuple<0, Ts... >(result, vars);
121 PyObject * toPy(const std::vector<T>& values)
123 PyObject * result = PyList_New(values.size());
124 for(std::size_t i = 0; i < values.size(); ++i)
125 PyList_SetItem(result, i, toPy(values[i]));
130 PyObject * toPy(const std::list<T>& values)
132 PyObject * result = PyList_New(values.size());
134 for(const T& it : values)
136 PyList_SetItem(result, i, toPy(it));
142 template <class K, class V>
143 PyObject * toPy(const std::map<K, V>& values)
145 PyObject * result = PyDict_New();
146 for(const auto& it: values)
148 PyPtr pyKey(toPy(it.first));
149 PyPtr pyValue(toPy(it.second));
150 PyDict_SetItem(result, pyKey.get(), pyValue.get());
155 template<std::size_t I = 0, class ...Ts>
156 inline typename std::enable_if<I == sizeof...(Ts), ConversionCheck>::type
157 getFromPyTuple(PyObject * tup, std::tuple<Ts&...>& vars )
159 return ConversionCheck();
162 template<std::size_t I = 0, class ...Ts>
163 inline typename std::enable_if<I < sizeof...(Ts), ConversionCheck>::type
164 getFromPyTuple(PyObject * tup, std::tuple<Ts&...>& vars )
166 ConversionCheck check;
167 PyObject * obj = PyTuple_GetItem(tup, I);
168 typedef typename std::tuple_element<I, std::tuple<Ts...> >::type T;
169 check.addError(fromPy(obj, std::get<I>(vars)));
171 check.addError(getFromPyTuple<I+1, Ts...>(tup, vars));
175 template<class ...Ts>
176 ConversionCheck fromPy(PyObject * obj, std::tuple<Ts&...>& vars)
178 ConversionCheck check;
181 if(PyTuple_Check(obj) &&
182 PyTuple_Size(obj) == std::tuple_size<std::tuple<Ts&...> >::value)
184 check.addError(getFromPyTuple<0, Ts...>(obj, vars));
187 if(1 == std::tuple_size<std::tuple<Ts&...> >::value)
189 check.addError(fromPy(obj, std::get<0>(vars)));
192 check.addError("std::tuple", obj);
195 check.addError("std::tuple", obj);
200 ConversionCheck fromPy( PyObject *obj, std::vector<T>& result)
202 ConversionCheck check;
203 if(PyList_Check(obj))
206 std::size_t size = PyList_Size(obj);
208 for(std::size_t i=0; i < size && check; i++)
209 check.addError(fromPy(PyList_GetItem(obj, i), result[i]));
211 check.addError("std::vector", obj);
213 else if(PyTuple_Check(obj))
216 std::size_t size = PyTuple_Size(obj);
218 for(std::size_t i=0; i < size && check; i++)
219 check.addError(fromPy(PyTuple_GetItem(obj, i), result[i]));
221 check.addError("std::vector", obj);
224 check.addError("std::vector", obj);
229 ConversionCheck fromPy( PyObject *obj, std::list<T>& result)
231 ConversionCheck check;
232 if(PyList_Check(obj))
235 std::size_t size = PyList_Size(obj);
236 result.resize(size); //result will have "size" default constructed elements.
240 check.addError(fromPy(PyList_GetItem(obj, i), it));
243 check.addError("std::list", obj);
249 else if(PyTuple_Check(obj))
252 std::size_t size = PyTuple_Size(obj);
253 result.resize(size); //result will have "size" default constructed elements.
257 check.addError(fromPy(PyTuple_GetItem(obj, i), it));
260 check.addError("std::list", obj);
267 check.addError("std::list", obj);
271 template <class K, class V>
272 ConversionCheck fromPy( PyObject *obj, std::map<K, V>& result)
274 ConversionCheck check;
275 if(PyDict_Check(obj))
278 PyPtr pyKeys(PyDict_Keys(obj));
279 std::size_t size = PyList_Size(pyKeys.get());
280 for(std::size_t i =0; i < size && check; ++i)
282 PyObject * curKey = PyList_GetItem(pyKeys.get(), i);
285 check.addError(fromPy(curKey, key));
287 check.addError(fromPy(PyDict_GetItem(obj, curKey), value));
291 check.addError("std::map", obj);
295 check.addError("std::map", obj);
301 T fromPyPtr( const PyPtr& py)
304 fromPy(py.get(), result);
309 ConversionCheck fromPyPtr( const PyPtr& py, T& var)
311 return fromPy(py.get(), var);
315 PyPtr toPyPtr(const T& v)
317 return PyPtr(toPy(v));
321 T fromPy( PyObject *po)
324 ConversionCheck check;
325 check = fromPy(po, result);
327 throw ConversionException(check.getMessage());
332 #endif //PY2CPP_TYPECONVERSIONS_HXX