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);
214 check.addError("std::vector", obj);
219 ConversionCheck fromPy( PyObject *obj, std::list<T>& result)
221 ConversionCheck check;
222 if(PyList_Check(obj))
225 std::size_t size = PyList_Size(obj);
226 result.resize(size); //result will have "size" default constructed elements.
230 check.addError(fromPy(PyList_GetItem(obj, i), it));
233 check.addError("std::list", obj);
240 check.addError("std::list", obj);
244 template <class K, class V>
245 ConversionCheck fromPy( PyObject *obj, std::map<K, V>& result)
247 ConversionCheck check;
248 if(PyDict_Check(obj))
251 PyPtr pyKeys(PyDict_Keys(obj));
252 std::size_t size = PyList_Size(pyKeys.get());
253 for(std::size_t i =0; i < size && check; ++i)
255 PyObject * curKey = PyList_GetItem(pyKeys.get(), i);
258 check.addError(fromPy(curKey, key));
260 check.addError(fromPy(PyDict_GetItem(obj, curKey), value));
264 check.addError("std::map", obj);
268 check.addError("std::map", obj);
274 T fromPyPtr( const PyPtr& py)
277 fromPy(py.get(), result);
282 ConversionCheck fromPyPtr( const PyPtr& py, T& var)
284 return fromPy(py.get(), var);
288 PyPtr toPyPtr(const T& v)
290 return PyPtr(toPy(v));
294 T fromPy( PyObject *po)
297 ConversionCheck check;
298 check = fromPy(po, result);
300 throw ConversionException(check.getMessage());
305 #endif //PY2CPP_TYPECONVERSIONS_HXX