title: Accessing view of a NumPy array using the C API
body: <p>In a Python extension module I've written in C++, I use the following snippet of code to convert a NumPy array into an <a href="http://arma.sourceforge.net/" rel="nofollow noreferrer">Armadillo</a> array for use in the C++ portion of the code:</p>
  <pre class="lang-cpp prettyprint-override"><code>static arma::mat convertPyArrayToArma(PyArrayObject* pyarr, int nrows, int ncols)
  {
      // Check if the dimensions are what I expect.
      if (!checkPyArrayDimensions(pyarr, nrows, ncols)) throw WrongDimensions();
      
      const std::vector&lt;int&gt; dims = getPyArrayDimensions(pyarr);  // Gets the dimensions using the API
      
      PyArray_Descr* reqDescr = PyArray_DescrFromType(NPY_DOUBLE);
      if (reqDescr == NULL) throw std::bad_alloc();
      
      // Convert the array to Fortran-ordering as required by Armadillo
      PyArrayObject* cleanArr = (PyArrayObject*)PyArray_FromArray(pyarr, reqDescr, 
                                                                  NPY_ARRAY_FARRAY);
      if (cleanArr == NULL) throw std::bad_alloc();
      reqDescr = NULL;  // The new reference from DescrFromType was stolen by FromArray
  
      double* dataPtr = static_cast&lt;double*&gt;(PyArray_DATA(cleanArr));
      arma::mat result (dataPtr, dims[0], dims[1], true);  // this copies the data from cleanArr
      Py_DECREF(cleanArr);
      return result;
  }
  </code></pre>
  <p>The problem is that when I pass this a <em>view</em> of a NumPy array (i.e. <code>my_array[:, 3]</code>), it doesn't seem to handle the strides of the underlying C array correctly. Based on the output, it seems like the array <code>pyarr</code> received by the function is actually the full base array, and not the view (or at least when I access the data using <code>PyArray_DATA</code>, I seem to be getting a pointer to the full base array). If I instead pass this function a copy of the view (i.e. <code>my_array[:, 3].copy()</code>), it works as expected, but I don't want to have to remember to do that every time.</p>
  <p>So, is there a way to make <code>PyArray_FromArray</code> copy only the slice of the matrix I want? I tried using the flag <code>NPY_ARRAY_ENSURECOPY</code>, but that didn't help.</p>
  <h1>Edit 1</h1>
  <p>As suggested in the comments, here is a full working example:</p>
  <p>In file <code>example.cpp</code>:</p>
  <pre class="lang-cpp prettyprint-override"><code>#define NPY_NO_DEPRECATED_API NPY_1_9_API_VERSION
  
  extern &quot;C&quot; {
      #include &lt;Python.h&gt;
      #include &lt;numpy/arrayobject.h&gt;
  }
  #include &lt;exception&gt;
  #include &lt;cassert&gt;
  #include &lt;string&gt;
  #include &lt;type_traits&gt;
  #include &lt;map&gt;
  #include &lt;vector&gt;
  #include &lt;armadillo&gt;
  
  class WrongDimensions : public std::exception
  {
  public:
      WrongDimensions() {}
      const char* what() const noexcept { return msg.c_str(); }
  
  private:
      std::string msg = &quot;The dimensions were incorrect&quot;;
  };
  
  class NotImplemented : public std::exception
  {
  public:
      NotImplemented() {}
      const char* what() const noexcept { return msg.c_str(); }
  
  private:
      std::string msg = &quot;Not implemented&quot;;
  };
  
  class BadArrayLayout : public std::exception
  {
  public:
      BadArrayLayout() {}
      const char* what() const noexcept { return msg.c_str(); }
  
  private:
      std::string msg = &quot;The matrix was not contiguous&quot;;
  };
  
  static const std::vector&lt;npy_intp&gt; getPyArrayDimensions(PyArrayObject* pyarr)
  {
      npy_intp ndims = PyArray_NDIM(pyarr);
      npy_intp* dims = PyArray_SHAPE(pyarr);
      std::vector&lt;npy_intp&gt; result;
      for (int i = 0; i &lt; ndims; i++) {
          result.push_back(dims[i]);
      }
      return result;
  }
  
  /* Checks the dimensions of the given array. Pass -1 for either dimension to say you don't
   * care what the size is in that dimension. Pass dimensions (X, 1) for a vector.
   */
  static bool checkPyArrayDimensions(PyArrayObject* pyarr, const npy_intp dim0, const npy_intp dim1)
  {
      const auto dims = getPyArrayDimensions(pyarr);
      assert(dims.size() &lt;= 2 &amp;&amp; dims.size() &gt; 0);
      if (dims.size() == 1) {
          return (dims[0] == dim0 || dim0 == -1) &amp;&amp; (dim1 == 1 || dim1 == -1);
      }
      else {
          return (dims[0] == dim0 || dim0 == -1) &amp;&amp; (dims[1] == dim1 || dim1 == -1);
      }
  }
  
  template&lt;typename outT&gt;
  static arma::Mat&lt;outT&gt; convertPyArrayToArma(PyArrayObject* pyarr, int nrows, int ncols)
  {
      if (!checkPyArrayDimensions(pyarr, nrows, ncols)) throw WrongDimensions();
  
      int arrTypeCode;
      if (std::is_same&lt;outT, uint16_t&gt;::value) {
          arrTypeCode = NPY_UINT16;
      }
      else if (std::is_same&lt;outT, double&gt;::value) {
          arrTypeCode = NPY_DOUBLE;
      }
      else {
          throw NotImplemented();
      }
  
      const auto dims = getPyArrayDimensions(pyarr);
      if (dims.size() == 1) {
          outT* dataPtr = static_cast&lt;outT*&gt;(PyArray_DATA(pyarr));
          return arma::Col&lt;outT&gt;(dataPtr, dims[0], true);
      }
      else {
          PyArray_Descr* reqDescr = PyArray_DescrFromType(arrTypeCode);
          if (reqDescr == NULL) throw std::bad_alloc();
          PyArrayObject* cleanArr = (PyArrayObject*)PyArray_FromArray(pyarr, reqDescr, NPY_ARRAY_FARRAY);
          if (cleanArr == NULL) throw std::bad_alloc();
          reqDescr = NULL;  // The new reference from DescrFromType was stolen by FromArray
  
          outT* dataPtr = static_cast&lt;outT*&gt;(PyArray_DATA(cleanArr));
          arma::Mat&lt;outT&gt; result (dataPtr, dims[0], dims[1], true);  // this copies the data from cleanArr
          Py_DECREF(cleanArr);
          return result;
      }
  }
  
  static PyObject* convertArmaToPyArray(const arma::mat&amp; matrix)
  {
      npy_intp ndim = matrix.is_colvec() ? 1 : 2;
      npy_intp nRows = static_cast&lt;npy_intp&gt;(matrix.n_rows);  // NOTE: This narrows the integer
      npy_intp nCols = static_cast&lt;npy_intp&gt;(matrix.n_cols);
      npy_intp dims[2] = {nRows, nCols};
  
      PyObject* result = PyArray_SimpleNew(ndim, dims, NPY_DOUBLE);
      if (result == NULL) throw std::bad_alloc();
  
      double* resultDataPtr = static_cast&lt;double*&gt;(PyArray_DATA((PyArrayObject*)result));
      for (int i = 0; i &lt; nRows; i++) {
          for (int j = 0; j &lt; nCols; j++) {
              resultDataPtr[i * nCols + j] = matrix(i, j);
          }
      }
  
      return result;
  }
  
  extern &quot;C&quot; {
      // An example function that takes a NumPy array and converts it to
      // an arma::mat and back. This should return the array unchanged.
      static PyObject* example_testFunction(PyObject* self, PyObject* args)
      {
          PyArrayObject* myArray = NULL;
  
          if (!PyArg_ParseTuple(args, &quot;O!&quot;, &amp;PyArray_Type, &amp;myArray)) {
              return NULL;
          }
  
          PyObject* output = NULL;
          try {
              arma::mat myMat = convertPyArrayToArma&lt;double&gt;(myArray, -1, -1);
              output = convertArmaToPyArray(myMat);
          }
          catch (const std::bad_alloc&amp;) {
              PyErr_NoMemory();
              Py_XDECREF(output);
              return NULL;
          }
          catch (const std::exception&amp; err) {
              PyErr_SetString(PyExc_RuntimeError, err.what());
              Py_XDECREF(output);
              return NULL;
          }
  
          return output;
      }
  
      static PyMethodDef example_methods[] =
      {
          {&quot;test_function&quot;, example_testFunction, METH_VARARGS, &quot;A test function&quot;},
          {NULL, NULL, 0, NULL}
      };
  
      static struct PyModuleDef example_module = {
         PyModuleDef_HEAD_INIT,
         &quot;example&quot;,   /* name of module */
         NULL, /* module documentation, may be NULL */
         -1,       /* size of per-interpreter state of the module,
                      or -1 if the module keeps state in global variables. */
         example_methods
      };
  
      PyMODINIT_FUNC
      PyInit_example(void)
      {
          import_array();
  
          PyObject* m = PyModule_Create(&amp;example_module);
          if (m == NULL) return NULL;
          return m;
      }
  }
  </code></pre>
  <p>And <code>setup.py</code> for compiling:</p>
  <pre><code>from setuptools import setup, Extension
  import numpy as np
  
  example_module = Extension(
      'example',
      include_dirs=[np.get_include(), '/usr/local/include'],
      libraries=['armadillo'],
      library_dirs=['/usr/local/lib'],
      sources=['example.cpp'],
      language='c++',
      extra_compile_args=['-std=c++11', '-mmacosx-version-min=10.10'],
      )
  
  setup(name='example',
        ext_modules=[example_module],
        )
  </code></pre>
  <p>Now assume we have the example array</p>
  <pre><code>a = np.array([[ 1, 2, 3, 4, 5, 6], 
                [ 7, 8, 9,10,11,12], 
                [13,14,15,16,17,18]], dtype='float64')
  </code></pre>
  <p>The function seems to work fine for multidimensional slices like <code>a[:, :3]</code>, and it returns the matrix unaltered as I'd expect. But if I give it a single-dimensional slice, I get the wrong components unless I make a copy:</p>
  <pre><code>&gt;&gt;&gt; example.test_function(a[:, 3])
  array([ 4.,  5.,  6.])
  
  &gt;&gt;&gt; example.test_function(a[:, 3].copy())
  array([  4.,  10.,  16.])
  </code></pre>