1

Following examples and the numpy C-API (http://docs.scipy.org/doc/numpy/reference/c-api.html), I'm trying to access numpy array data in cpp, like this:

#include <Python.h>
#include <frameobject.h>
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION // TOGGLE OR NOT
#include "numpy/ndarraytypes.h"
#include "numpy/arrayobject.h"
...
// here I have passed "some_python_object" to the C code
// .. and "some_python_object" has member "infobuf" that is a numpy array
//
unsigned long* fInfoBuffer;
PyObject* infobuffer = PyObject_GetAttrString(some_python_object, "infobuf");
PyObject* x_array    = PyArray_FROM_OT(infobuffer, NPY_UINT32);
fInfoBuffer          = (unsigned long*)PyArray_DATA(x_array); // DOES NOT WORK WHEN API DEPRECATION IS TOGGLED

When the API deprecation is toggled, I get, when compiling:

error: cannot convert ‘PyObject* {aka _object*}’ to ‘PyArrayObject* {aka tagPyArrayObject*}’ for argument ‘1’ to ‘void* PyArray_DATA(PyArrayObject*)’

What would be the legitimate way of doing this in numpy 1.7+ ?

El Sampsa
  • 1,673
  • 3
  • 17
  • 33

2 Answers2

2

You could try using a higher-level library that wraps numpy arrays in C++ containers with proper container semantics.

Try out xtensor and the xtensor-python bindings.

There is also a cookiecutter to generate a minimal C++ extension project with all the boilerplate for testing, html documentation and setup.p...

Example: C++ code

#include <numeric>                        // Standard library import for std::accumulate
#include "pybind11/pybind11.h"            // Pybind11 import to define Python bindings
#include "xtensor/xmath.hpp"              // xtensor import for the C++ universal functions
#define FORCE_IMPORT_ARRAY                // numpy C api loading
#include "xtensor-python/pyarray.hpp"     // Numpy bindings

double sum_of_sines(xt::pyarray<double> &m)
{
    auto sines = xt::sin(m);
    // sines does not actually hold any value, which are only computed upon access
    return std::accumulate(sines.begin(), sines.end(), 0.0);
}

PYBIND11_PLUGIN(xtensor_python_test)
{
    xt::import_numpy();
    pybind11::module m("xtensor_python_test", "Test module for xtensor python bindings");

    m.def("sum_of_sines", sum_of_sines,
        "Computes the sum of the sines of the values of the input array");

    return m.ptr();
}

Python Code:

import numpy as np
import xtensor_python_test as xt

a = np.arange(15).reshape(3, 5)
s = xt.sum_of_sines(v)
s
Quant
  • 1,593
  • 14
  • 21
  • Question refered to the C-API, the answer related to C++ code. The question remains, how would one do this using the C-API. – rhody Feb 02 '18 at 04:11
  • 2
    The C++ code in question makes use of the C API, and wraps it in higher level constructs. Also, the original question says "I'm trying to access numpy array data in cpp," – Quant Feb 02 '18 at 21:28
0

It is because PyArray_DATA expects a PyArrayObject*. You can try to change the type of x_array:

PyArrayObject* x_array = (PyArrayObject*) PyArray_FROM_OT(infobuffer, NPY_UINT32)
RemiDav
  • 463
  • 3
  • 16