Nektar++
Public Member Functions | Static Public Member Functions | List of all members
PythonToOneDArray< T > Struct Template Reference

Converter for Python to Nektar::Array<OneD, T>. More...

#include <SharedArray.hpp>

Public Member Functions

 PythonToOneDArray ()
 Default constructor. More...
 

Static Public Member Functions

static void * convertible (PyObject *objPtr)
 Determine whether the given objPtr is convertible to convertible to an Array type or not. More...
 
template<typename U = T, std::enable_if_t< std::is_arithmetic< U >::value > * = nullptr>
static bool try_convertible (py::object &obj)
 
template<typename U = T, std::enable_if_t< is_shared_ptr< U >::value||is_nekarray_oned< U >::value > * = nullptr>
static bool try_convertible (py::object &obj)
 
static void decrement (void *objPtr)
 
static void construct (PyObject *objPtr, py::converter::rvalue_from_python_stage1_data *data)
 
template<typename U = T, std::enable_if_t< std::is_arithmetic< U >::value > * = nullptr>
static void construct_impl (PyObject *objPtr, py::converter::rvalue_from_python_stage1_data *data)
 
template<typename U = T, std::enable_if_t< is_shared_ptr< U >::value||is_nekarray_oned< U >::value > * = nullptr>
static void construct_impl (PyObject *objPtr, py::converter::rvalue_from_python_stage1_data *data)
 

Detailed Description

template<typename T>
struct PythonToOneDArray< T >

Converter for Python to Nektar::Array<OneD, T>.

Definition at line 148 of file Python/BasicUtils/SharedArray.hpp.

Constructor & Destructor Documentation

◆ PythonToOneDArray()

template<typename T >
PythonToOneDArray< T >::PythonToOneDArray ( )
inline

Default constructor.

Definition at line 151 of file Python/BasicUtils/SharedArray.hpp.

152 {
153 py::converter::registry::push_back(&convertible, &construct,
154 py::type_id<Array<OneD, T>>());
155 }
static void construct(PyObject *objPtr, py::converter::rvalue_from_python_stage1_data *data)
static void * convertible(PyObject *objPtr)
Determine whether the given objPtr is convertible to convertible to an Array type or not.

References PythonToOneDArray< T >::construct(), and PythonToOneDArray< T >::convertible().

Member Function Documentation

◆ construct()

template<typename T >
static void PythonToOneDArray< T >::construct ( PyObject *  objPtr,
py::converter::rvalue_from_python_stage1_data *  data 
)
inlinestatic

Definition at line 246 of file Python/BasicUtils/SharedArray.hpp.

248 {
249 construct_impl(objPtr, data);
250 }
static void construct_impl(PyObject *objPtr, py::converter::rvalue_from_python_stage1_data *data)

References PythonToOneDArray< T >::construct_impl().

Referenced by PythonToOneDArray< T >::PythonToOneDArray().

◆ construct_impl() [1/2]

template<typename T >
template<typename U = T, std::enable_if_t< std::is_arithmetic< U >::value > * = nullptr>
static void PythonToOneDArray< T >::construct_impl ( PyObject *  objPtr,
py::converter::rvalue_from_python_stage1_data *  data 
)
inlinestatic

Definition at line 254 of file Python/BasicUtils/SharedArray.hpp.

256 {
257 // This has to be a _borrowed_ reference, otherwise at the end of this
258 // scope it seems memory gets deallocated
259 py::object obj(py::handle<>(py::borrowed(objPtr)));
260 np::ndarray array = py::extract<np::ndarray>(obj);
261
262 // If this array came from C++, extract the C++ array from PyCObject or
263 // PyCapsule and ensure that we set up the C++ array to have a reference
264 // to that object, so that it can be decremented as appropriate.
265 py::object base = array.get_base();
266 Array<OneD, T> *ptr = nullptr;
267
268#if PY_MAJOR_VERSION == 2
269 if (PyCObject_Check(base.ptr()))
270 {
271 ptr = reinterpret_cast<Array<OneD, T> *>(
272 PyCObject_AsVoidPtr(base.ptr()));
273 }
274#else
275 if (PyCapsule_CheckExact(base.ptr()))
276 {
277 ptr = reinterpret_cast<Array<OneD, T> *>(
278 PyCapsule_GetPointer(base.ptr(), nullptr));
279 }
280#endif
281
282 void *storage =
283 ((py::converter::rvalue_from_python_storage<Array<OneD, T>> *)data)
284 ->storage.bytes;
285 data->convertible = storage;
286
287 using nonconst_t = typename std::remove_const<T>::type;
288 new (storage)
289 Array<OneD, T>(array.shape(0), (nonconst_t *)array.get_data(),
290 (void *)objPtr, &decrement);
291 py::incref(objPtr);
292 }
static void decrement(void *objPtr)

References PythonToOneDArray< T >::decrement().

Referenced by PythonToOneDArray< T >::construct().

◆ construct_impl() [2/2]

template<typename T >
template<typename U = T, std::enable_if_t< is_shared_ptr< U >::value||is_nekarray_oned< U >::value > * = nullptr>
static void PythonToOneDArray< T >::construct_impl ( PyObject *  objPtr,
py::converter::rvalue_from_python_stage1_data *  data 
)
inlinestatic

Definition at line 297 of file Python/BasicUtils/SharedArray.hpp.

299 {
300 using nonconst_t = typename std::remove_const<T>::type;
301
302 py::object obj(py::handle<>(py::borrowed(objPtr)));
303 py::list l = py::extract<py::list>(obj);
304
305 const std::size_t nItems = py::len(l);
306
307 // Allocate some storage for the Array.
308 void *storage =
309 ((py::converter::rvalue_from_python_storage<Array<OneD, nonconst_t>>
310 *)data)
311 ->storage.bytes;
313 new (storage) Array<OneD, nonconst_t>(nItems);
314 data->convertible = storage;
315
316 // Fill the Array.
317 for (std::size_t i = 0; i < nItems; ++i)
318 {
319 (*tmp)[i] = py::extract<nonconst_t>(l[i]);
320 }
321 }

◆ convertible()

template<typename T >
static void * PythonToOneDArray< T >::convertible ( PyObject *  objPtr)
inlinestatic

Determine whether the given objPtr is convertible to convertible to an Array type or not.

This is a top-level function: different data types are handled separately in the ::try_convertible functions.

Definition at line 164 of file Python/BasicUtils/SharedArray.hpp.

165 {
166 try
167 {
168 py::object obj((py::handle<>(py::borrowed(objPtr))));
169 return try_convertible(obj) ? objPtr : nullptr;
170 }
171 catch (boost::python::error_already_set &)
172 {
173 py::handle_exception();
174 PyErr_Clear();
175 return nullptr;
176 }
177 }
static bool try_convertible(py::object &obj)

References PythonToOneDArray< T >::try_convertible().

Referenced by PythonToOneDArray< T >::PythonToOneDArray().

◆ decrement()

template<typename T >
static void PythonToOneDArray< T >::decrement ( void *  objPtr)
inlinestatic

Definition at line 232 of file Python/BasicUtils/SharedArray.hpp.

233 {
234 if (!Py_IsInitialized())
235 {
236 // In deinitialisation phase, reference counters are not terribly
237 // robust; decremementing counters here can lead to segfaults during
238 // program exit in some cases.
239 return;
240 }
241
242 // Otherwise decrement reference counter.
243 py::decref((PyObject *)objPtr);
244 }

Referenced by PythonToOneDArray< T >::construct_impl().

◆ try_convertible() [1/2]

template<typename T >
template<typename U = T, std::enable_if_t< std::is_arithmetic< U >::value > * = nullptr>
static bool PythonToOneDArray< T >::try_convertible ( py::object &  obj)
inlinestatic

Definition at line 181 of file Python/BasicUtils/SharedArray.hpp.

182 {
183 np::ndarray array = py::extract<np::ndarray>(obj);
184
185 // Check data types match
186 np::dtype dtype =
187 np::dtype::get_builtin<typename std::remove_const<U>::type>();
188 if (dtype != array.get_dtype())
189 {
190 return false;
191 }
192
193 // Check shape is 1D
194 if (array.get_nd() != 1)
195 {
196 return false;
197 }
198
199 return true;
200 }

Referenced by PythonToOneDArray< T >::convertible().

◆ try_convertible() [2/2]

template<typename T >
template<typename U = T, std::enable_if_t< is_shared_ptr< U >::value||is_nekarray_oned< U >::value > * = nullptr>
static bool PythonToOneDArray< T >::try_convertible ( py::object &  obj)
inlinestatic

Definition at line 205 of file Python/BasicUtils/SharedArray.hpp.

206 {
207 py::extract<py::list> list_conv(obj);
208
209 if (!list_conv.check())
210 {
211 return false;
212 }
213
214 py::list l = list_conv();
215 const std::size_t nItems = py::len(l);
216
217 // We'll need to construct a temporary vector to hold each item in the
218 // list.
219 for (std::size_t i = 0; i < nItems; ++i)
220 {
221 py::extract<T> item_conv(l[i]);
222
223 if (!py::extract<T>(l[i]).check())
224 {
225 return false;
226 }
227 }
228
229 return true;
230 }