2010-10-09 47 views
2

我想將numpy數組轉換爲C++端的一些double *或stl向量。我實際上使用PyCXX,我無法弄清楚訪問數據的方式。如何訪問PyCXX中的numpy數組

我目前能夠這樣來訪問和返回數據緩衝區:

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。