only do numpy contiguous C/Fortran array conversion when explicitly requested

This commit is contained in:
Wenzel Jakob 2016-05-05 10:00:00 +02:00
parent 876eeab4ca
commit f1032df891
2 changed files with 28 additions and 8 deletions

View File

@ -902,16 +902,30 @@ type of Python object satisfying the buffer protocol).
In many situations, we want to define a function which only accepts a NumPy In many situations, we want to define a function which only accepts a NumPy
array of a certain data type. This is possible via the ``py::array_t<T>`` array of a certain data type. This is possible via the ``py::array_t<T>``
template. For instance, the following function requires the argument to be a template. For instance, the following function requires the argument to be a
dense array of doubles in C-style ordering. NumPy array containing double precision values.
.. code-block:: cpp .. code-block:: cpp
void f(py::array_t<double> array); void f(py::array_t<double> array);
When it is invoked with a different type (e.g. an integer), the binding code When it is invoked with a different type (e.g. an integer or a list of
will attempt to cast the input into a NumPy array of the requested type. Note integers), the binding code will attempt to cast the input into a NumPy array
that this feature requires the :file:``pybind11/numpy.h`` header to be of the requested type. Note that this feature requires the
included. :file:``pybind11/numpy.h`` header to be included.
Data in NumPy arrays is not guaranteed to packed in a dense manner;
furthermore, entries can be separated by arbitrary column and row strides.
Sometimes, it can be useful to require a function to only accept dense arrays
using either the C (row-major) or Fortran (column-major) ordering. This can be
accomplished via a second template argument with values ``py::array::c_style``
or ``py::array::f_style``.
.. code-block:: cpp
void f(py::array_t<double, py::array::c_style> array);
As before, the implementation will attempt to convert non-conforming arguments
into an array satisfying the specified requirements.
Vectorizing functions Vectorizing functions
===================== =====================

View File

@ -77,6 +77,11 @@ public:
PYBIND11_OBJECT_DEFAULT(array, buffer, lookup_api().PyArray_Check_) PYBIND11_OBJECT_DEFAULT(array, buffer, lookup_api().PyArray_Check_)
enum {
c_style = API::NPY_C_CONTIGUOUS_,
f_style = API::NPY_F_CONTIGUOUS_
};
template <typename Type> array(size_t size, const Type *ptr) { template <typename Type> array(size_t size, const Type *ptr) {
API& api = lookup_api(); API& api = lookup_api();
PyObject *descr = api.PyArray_DescrFromType_(npy_format_descriptor<Type>::value); PyObject *descr = api.PyArray_DescrFromType_(npy_format_descriptor<Type>::value);
@ -120,7 +125,7 @@ protected:
} }
}; };
template <typename T> class array_t : public array { template <typename T, int ExtraFlags = 0> class array_t : public array {
public: public:
PYBIND11_OBJECT_CVT(array_t, array, is_non_null, m_ptr = ensure(m_ptr)); PYBIND11_OBJECT_CVT(array_t, array, is_non_null, m_ptr = ensure(m_ptr));
array_t() : array() { } array_t() : array() { }
@ -131,8 +136,9 @@ public:
API &api = lookup_api(); API &api = lookup_api();
PyObject *descr = api.PyArray_DescrFromType_(npy_format_descriptor<T>::value); PyObject *descr = api.PyArray_DescrFromType_(npy_format_descriptor<T>::value);
PyObject *result = api.PyArray_FromAny_( PyObject *result = api.PyArray_FromAny_(
ptr, descr, 0, 0, API::NPY_C_CONTIGUOUS_ | API::NPY_ENSURE_ARRAY_ ptr, descr, 0, 0,
| API::NPY_ARRAY_FORCECAST_, nullptr); API::NPY_ENSURE_ARRAY_ | API::NPY_ARRAY_FORCECAST_ | ExtraFlags,
nullptr);
Py_DECREF(ptr); Py_DECREF(ptr);
return result; return result;
} }