5

This is my first question on this site.

First of all, I need to make a module with one function for python in C++, which must work with numpy, using <numpy/arrayobject.h>. This function takes one numpy array and returns two numpy arrays. All arrays are one-dimensional.

The first question is how to get the data from a numpy array? I want to collect the information from array in std::vector, so then I can easily work with it C++.

The second: am I right that function should return a tuple of arrays, then user of my module can write like this in python: arr1, arr2 = foo(arr) ? And how to return like this?

Thank you very much.

2

1 Answer 1

5

NumPy includes lots of functions and macros that make it pretty easy to access the data of an ndarray object within a C or C++ extension. Given a 1D ndarray called v, one can access element i with PyArray_GETPTR1(v, i). So if you want to copy each element in the array to a std::vector of the same type, you can iterate over each element and copy it, like so (I'm assuming an array of doubles):

npy_intp vsize = PyArray_SIZE(v);
std::vector<double> out(vsize);
for (int i = 0; i < vsize; i++) {
    out[i] = *reinterpret_cast<double*>(PyArray_GETPTR1(v, i));
}

One could also do a bulk memcpy-like operation, but keep in mind that NumPy ndarrays may be mis-aligned for the data type, have non-native byte order, or other subtle attributes that make such copies less than desirable. But assuming that you are aware of these, one could do:

npy_intp vsize = PyArray_SIZE(v);
std::vector<double> out(vsize);
std::memcpy(out.data(), PyArray_DATA(v), sizeof(double) * vsize);

Using either approach, out now contains a copy of the ndarray's data, and you can manipulate it however you like. Keep in mind that, unless you really need the data as a std::vector, the NumPy C API may be perfectly fine to use in your extension as a way to access and manipulate the data. That is, unless you need to pass the data to some other function which must take a std::vector or you want to use C++ library code that relies on std::vector, I'd consider doing all your processing directly on the native array types.

As to your last question, one generally uses PyArg_BuildValue to construct a tuple which is returned from your extension functions. Your tuple would just contain two ndarray objects.

Sign up to request clarification or add additional context in comments.

7 Comments

Thank you a lot! So, I can also get information about the shape of a numpy array by calling the function PyArray_GetArrayParamsFromObject? And then I want returning object's shape will be the same
@InFamousX That'll work just fine, but it's more common to use the macros PyArray_NDIM() and PyArray_DIMS(). The former function is more often used for converting a Python-native object (like a list-of-lists) to an ndarray.
Sorry, but this cycle for(int ...) doesn't work properly, because I get from it only zeros.
@InFamousX That loop should access the data fine, are you sure that the array itself is not all zeros?
Thank you, I found another way to get the data. My mistake was that I didn't know that float in python is the same as double in c++. That's why I got nothing but zeros.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.