1 // Copyright (C) 2019-2023 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
21 #include "py2cppExports.hxx"
35 * toPy functions return a new python object built from a c++ object.
36 * The conversion is always possible and it does not throw exceptions.
38 PY2CPP_EXPORT PyObject * toPy(int);
39 PY2CPP_EXPORT PyObject * toPy(unsigned int);
40 PY2CPP_EXPORT PyObject * toPy(bool);
41 PY2CPP_EXPORT PyObject * toPy(double);
42 PY2CPP_EXPORT PyObject * toPy(const std::string&);
43 PY2CPP_EXPORT PyObject * toPy(const char*);
44 PY2CPP_EXPORT PyObject * toPy(PyObject *);
45 PY2CPP_EXPORT PyObject * toPy(const PyPtr&);
47 PY2CPP_EXPORT PyObject * toPy(const std::vector<T>& values);
49 PY2CPP_EXPORT PyObject * toPy(const std::list<T>& values);
50 template <class K, class V>
51 PY2CPP_EXPORT PyObject * toPy(const std::map<K, V>& values);
53 PY2CPP_EXPORT PyObject * toPy(const std::tuple<Ts...>& vars );
56 * fromPy functions convert a python object to a c++ object.
57 * If the convertion fails, the ConversionCheck object returned contains the
58 * error message. No exception is thrown.
60 PY2CPP_EXPORT ConversionCheck fromPy( PyObject *, int&);
61 PY2CPP_EXPORT ConversionCheck fromPy( PyObject *, unsigned int&);
62 PY2CPP_EXPORT ConversionCheck fromPy( PyObject *, bool&);
63 PY2CPP_EXPORT ConversionCheck fromPy( PyObject *, double&);
64 PY2CPP_EXPORT ConversionCheck fromPy( PyObject *, std::string&);
65 PY2CPP_EXPORT ConversionCheck fromPy( PyObject *, PyObject *&);
66 PY2CPP_EXPORT ConversionCheck fromPy( PyObject *, PyPtr&);
68 PY2CPP_EXPORT ConversionCheck fromPy(PyObject * obj, std::tuple<Ts&...>& vars);
70 PY2CPP_EXPORT ConversionCheck fromPy( PyObject *obj, std::vector<T>& result);
72 PY2CPP_EXPORT ConversionCheck fromPy( PyObject *obj, std::list<T>& result);
73 template <class K, class V>
74 PY2CPP_EXPORT ConversionCheck fromPy( PyObject *obj, std::map<K, V>& result);
76 /*! This templated version of fromPy throws ConversionException if the
80 PY2CPP_EXPORT T fromPy( PyObject *po);
82 // These versions of fromPy and toPy use PyPtr instead of PyObject *
84 PY2CPP_EXPORT T fromPyPtr( const PyPtr& py);
86 PY2CPP_EXPORT ConversionCheck fromPyPtr( const PyPtr& py, T& var);
88 PY2CPP_EXPORT PyPtr toPyPtr(const T& v);
90 PY2CPP_EXPORT PyPtr fromPy<PyPtr>( PyObject *po);
92 ////////////////////////////////////////////////////////////////////////////////
93 // Template implementations
94 ////////////////////////////////////////////////////////////////////////////////
97 template<std::size_t I = 0, class ...Ts>
98 inline typename std::enable_if<I == sizeof...(Ts), void>::type
99 addInPyTuple(PyObject * result, const std::tuple<Ts...>& vars )
103 template<std::size_t I = 0, class ...Ts>
104 inline typename std::enable_if<I < sizeof...(Ts), void>::type
105 addInPyTuple(PyObject * result, const std::tuple<Ts...>& vars )
107 PyObject * obj = toPy(std::get<I>(vars));
108 PyTuple_SetItem(result, I, obj);
109 addInPyTuple<I+1, Ts... >(result, vars);
112 template<class ...Ts>
113 PyObject * toPy(const std::tuple<Ts...>& vars )
115 PyObject * result = PyTuple_New(sizeof...(Ts));
116 addInPyTuple<0, Ts... >(result, vars);
122 PyObject * toPy(const std::vector<T>& values)
124 PyObject * result = PyList_New(values.size());
125 for(std::size_t i = 0; i < values.size(); ++i)
126 PyList_SetItem(result, i, toPy(values[i]));
131 PyObject * toPy(const std::list<T>& values)
133 PyObject * result = PyList_New(values.size());
135 for(const T& it : values)
137 PyList_SetItem(result, i, toPy(it));
143 template <class K, class V>
144 PyObject * toPy(const std::map<K, V>& values)
146 PyObject * result = PyDict_New();
147 for(const auto& it: values)
149 PyPtr pyKey(toPy(it.first));
150 PyPtr pyValue(toPy(it.second));
151 PyDict_SetItem(result, pyKey.get(), pyValue.get());
156 template<std::size_t I = 0, class ...Ts>
157 inline typename std::enable_if<I == sizeof...(Ts), ConversionCheck>::type
158 getFromPyTuple(PyObject * tup, std::tuple<Ts&...>& vars )
160 return ConversionCheck();
163 template<std::size_t I = 0, class ...Ts>
164 inline typename std::enable_if<I < sizeof...(Ts), ConversionCheck>::type
165 getFromPyTuple(PyObject * tup, std::tuple<Ts&...>& vars )
167 ConversionCheck check;
168 PyObject * obj = PyTuple_GetItem(tup, I);
169 typedef typename std::tuple_element<I, std::tuple<Ts...> >::type T;
170 check.addError(fromPy(obj, std::get<I>(vars)));
172 check.addError(getFromPyTuple<I+1, Ts...>(tup, vars));
176 template<class ...Ts>
177 ConversionCheck fromPy(PyObject * obj, std::tuple<Ts&...>& vars)
179 ConversionCheck check;
182 if(PyTuple_Check(obj) &&
183 PyTuple_Size(obj) == std::tuple_size<std::tuple<Ts&...> >::value)
185 check.addError(getFromPyTuple<0, Ts...>(obj, vars));
188 if(1 == std::tuple_size<std::tuple<Ts&...> >::value)
190 check.addError(fromPy(obj, std::get<0>(vars)));
193 check.addError("std::tuple", obj);
196 check.addError("std::tuple", obj);
201 ConversionCheck fromPy( PyObject *obj, std::vector<T>& result)
203 ConversionCheck check;
204 if(PyList_Check(obj))
207 std::size_t size = PyList_Size(obj);
209 for(std::size_t i=0; i < size && check; i++)
210 check.addError(fromPy(PyList_GetItem(obj, i), result[i]));
212 check.addError("std::vector", obj);
214 else if(PyTuple_Check(obj))
217 std::size_t size = PyTuple_Size(obj);
219 for(std::size_t i=0; i < size && check; i++)
220 check.addError(fromPy(PyTuple_GetItem(obj, i), result[i]));
222 check.addError("std::vector", obj);
225 check.addError("std::vector", obj);
230 ConversionCheck fromPy( PyObject *obj, std::list<T>& result)
232 ConversionCheck check;
233 if(PyList_Check(obj))
236 std::size_t size = PyList_Size(obj);
237 result.resize(size); //result will have "size" default constructed elements.
241 check.addError(fromPy(PyList_GetItem(obj, i), it));
244 check.addError("std::list", obj);
250 else if(PyTuple_Check(obj))
253 std::size_t size = PyTuple_Size(obj);
254 result.resize(size); //result will have "size" default constructed elements.
258 check.addError(fromPy(PyTuple_GetItem(obj, i), it));
261 check.addError("std::list", obj);
268 check.addError("std::list", obj);
272 template <class K, class V>
273 ConversionCheck fromPy( PyObject *obj, std::map<K, V>& result)
275 ConversionCheck check;
276 if(PyDict_Check(obj))
279 PyPtr pyKeys(PyDict_Keys(obj));
280 std::size_t size = PyList_Size(pyKeys.get());
281 for(std::size_t i =0; i < size && check; ++i)
283 PyObject * curKey = PyList_GetItem(pyKeys.get(), i);
286 check.addError(fromPy(curKey, key));
288 check.addError(fromPy(PyDict_GetItem(obj, curKey), value));
292 check.addError("std::map", obj);
296 check.addError("std::map", obj);
302 T fromPyPtr( const PyPtr& py)
305 fromPy(py.get(), result);
310 ConversionCheck fromPyPtr( const PyPtr& py, T& var)
312 return fromPy(py.get(), var);
316 PyPtr toPyPtr(const T& v)
318 return PyPtr(toPy(v));
322 T fromPy( PyObject *po)
325 ConversionCheck check;
326 check = fromPy(po, result);
328 throw ConversionException(check.getMessage());
333 #endif //PY2CPP_TYPECONVERSIONS_HXX