Как получить доступ к массиву NumPy внутри PyCXX - PullRequest
2 голосов
/ 09 октября 2010

Я хотел бы преобразовать массив numpy в какой-нибудь двойной * или stl вектор на стороне c ++.Я на самом деле использую PyCXX для этого, и я не могу выяснить способ доступа к данным.

В настоящее время я могу получить доступ и вернуть буфер данных, например так:1005 * Но я не знаю, что с этим делать.Моя конечная цель - получить из нее gsl_vector.В идеале мне не пришлось бы переписывать память.Но, может быть, это слишком много, чтобы спросить;)

1 Ответ

2 голосов
/ 19 ноября 2014

Когда я ищу решение и могу найти только тех, кто публикует тот же самый длинный без ответа вопрос, я публикую решение, как только обнаружу его. Ваш такой вопрос.

Во-первых, настоятельно рекомендуем использовать Cython в качестве клея и не двигаться дальше по этому опасному пути.

Это не так, использование PyArray_FromAny даст вам представление о базовых данных, если это возможно, и копию в противном случае. Очень простой пример (сборка с -std = c ++ 11, если вы честный и хороший человек, или VS2013, если вы пользователь Windows):

#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include <numpy/arrayobject.h>

Py::Object printNumpyArrayCxxFunction(const Py::Tuple& args)
{
    if(args.length() != 1)
    {
        throw Py::RuntimeError("Exactly one argument required.");
    }
    PyObject* vector_{PyArray_FromAny(*args[0], PyArray_DescrFromType(NPY_DOUBLE), 1, 1, NPY_ARRAY_CARRAY_RO, nullptr)};
    if(!vector_)
    {
        throw Py::ValueError("Failed to convert argument into a 1d numpy double (64-bit float) array.");
    }
    Py::Object vector(vector_, true);
    PyArrayObject* vector_npy{reinterpret_cast<PyArrayObject*>(vector_)};
    npy_intp vector_length{PyArray_SIZE(vector_npy)};
    double*const vector_begin{reinterpret_cast<double*>(PyArray_DATA(vector_npy))};
    double*const vector_end{vector_begin + vector_length};

    for(double* vector_iterator{vector_begin}; vector_iterator != vector_end; ++vector_iterator)
    {
        if(vector_iterator != vector_begin)
        {
            std::cout << ", ";
        }
        std::cout << *vector_iterator;
    }
    std::cout << std::endl;

    return Py::None();
}

Обратите внимание на истинный аргумент в качестве второго параметра для конструкторов Py :: Object для "собственных" объектов! Пример расширения cpython3, в котором для сборки используется API-интерфейс Numpy C в сочетании с PyCXX с cmake. Ссылка на конкретный коммит, поскольку я рассматриваю вопрос о возвращении этого расширения к использованию Cython.

...