Как получить данные из np.array в std::vector в C++, используя <numpy / arrayobject.h>?

Это мой первый вопрос на этом сайте.

Прежде всего, мне нужно сделать модуль с одной функцией для Python на C++, который должен работать с Numpy, используя <numpy/arrayobject.h>, Эта функция принимает один числовой массив и возвращает два пустых массива. Все массивы одномерные.

Первый вопрос: как получить данные из массива NumPy? Я хочу собрать информацию из массива в std::vector, чтобы потом я мог легко работать с ней C++.

Второе: я прав, что функция должна возвращать кортеж массивов, тогда пользователь моего модуля может написать так на python:arr1, arr2 = foo(arr)? И как вернуть так?

Большое спасибо.

1 ответ

Решение

NumPy включает в себя множество функций и макросов, которые облегчают доступ к данным ndarray объект в расширении C или C++. Учитывая 1D ndarray называется v можно получить доступ к элементу i с PyArray_GETPTR1(v, i), Так что если вы хотите скопировать каждый элемент в массиве в std::vector одного и того же типа, вы можете перебирать каждый элемент и копировать его, вот так (я предполагаю, что массив double s):

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));
}

Можно также сделать большую часть memcpy -подобная операция, но имейте ввиду, что NumPy ndarray s могут быть выровнены неправильно для типа данных, иметь не собственный порядок байтов или другие тонкие атрибуты, которые делают такие копии менее желательными. Но при условии, что вы знаете об этом, можно сделать:

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

Используя любой подход, out теперь содержит копию ndarray данные, и вы можете манипулировать ими так, как вам нравится. Имейте в виду, что, если вам не нужны данные как std::vector API-интерфейс NumPy C может прекрасно использоваться в вашем расширении для доступа к данным и манипулирования ими. То есть, если вам не нужно передавать данные в какую-то другую функцию, которая должна std::vector или вы хотите использовать код библиотеки C++, который опирается на std::vector Я хотел бы рассмотреть всю вашу обработку непосредственно на нативных типах массивов.

Что касается вашего последнего вопроса, один обычно использует PyArg_BuildValue построить кортеж, который возвращается из ваших функций расширения. Ваш кортеж будет содержать только два ndarray объекты.

Другие вопросы по тегам