Правильное или наиболее эффективное совместное использование Numpy массива объектов в C ++ Vector - PullRequest
0 голосов
/ 27 марта 2020

Я передаю Numpy данные в функцию расширения C ++, используя PyArg_ParseTuple. Одним из аргументов является массив Numpy объектов, т.е. dtype='O'. Эти объекты на самом деле являются одномерными Numpy массивами, но каждый имеет разную длину.

Мне удалось использовать следующий код, но как новичок в создании расширений python, мне интересно, есть ли лучший способ сделать это?

PyArrayObject *arr_neighbors=NULL;
PyArg_ParseTuple(args, "O!", &PyArray_Type, &arr_neighbors);

std::vector<long*> neighbors(n_polys);
std::vector<int> neighbor_lengths(n_polys);
for (long i = 0; i < n_polys; i++ ) {
  PyObject *array = PyArray_GETITEM(arr_neighbors, PyArray_GetPtr(arr_neighbors, &i));
  neighbor_lengths[i] = PyArray_DIM(array, 0);
  neighbors[i] = (long*) PyArray_DATA((PyArrayObject*) array);
}

1 Ответ

0 голосов
/ 28 марта 2020

Вы можете обмениваться данными между Python и C ++, избегая копирования, если вы размещаете их в C ++. Вот как это сделать для одного vector<long>, который вам нужно будет повторить для каждого в вашем внешнем векторе:

std::vector<long> vec; // TODO: populate

PyObject* dtype = PyString_FromString("i8");
PyArray_Descr* descr;
int rc = PyArray_DescrAlignConverter2(dtype.ptr(), &descr);
assert(rc == 1);

npy_intp dimension = vec.size();
PyObject* arr = PyArray_NewFromDescr(&PyArray_Type, descr, 1, &dimension,
        nullptr, vec.data(), 0/*flags*/, nullptr/*init*/));

Поскольку ваши данные поступают из Python, вы можете сделать vec.resize(N) с вышеупомянутым, чтобы эмулировать numpy.zeros(N, 'i8'), затем заполните значения в Python (который изменит вектор в C ++).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...