2010-10-09 3 views
2

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

Я в настоящее время в состоянии получить доступ и возвращает буфер данных, как это:

Py::Object arrayShape(const Py::Tuple& args){ 
    Py::Object array= args[0]; 
    return array.getAttr("data"); 
} 

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

ответ

2

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

Во-первых, настоятельно рекомендуем использовать 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 :: Объектные конструкторы для «принадлежащих» объектов! An example of a cpython3 extension that uses the Numpy C API in combination with PyCXX with cmake for building. Ссылка на конкретную фиксацию, потому что я рассматриваю возможность переключения этого расширения на использование Cython.