2010-10-09 7 views
2

Je voudrais convertir un tableau numpy en un vecteur double * ou stl du côté C++. J'utilise actuellement PyCXX pour cela et je n'arrive pas à trouver le moyen d'accéder aux données.Comment accéder au tableau numpy dans PyCXX

Je suis actuellement en mesure d'accéder et de retourner le tampon de données comme ceci:

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

Mais je ne sais pas quoi faire. Mon but final est d'obtenir un gsl_vector. Idéalement, je n'aurais pas à recopier la mémoire. Mais peut-être est-ce trop demander?)

Répondre

2

Lorsque je suis à la recherche d'une solution et que je ne trouve que d'autres personnes postant la même question, longtemps sans réponse, je poste la solution dès que je la découvre. Le vôtre est une telle question. Tout d'abord, pensez fortement à utiliser Cython comme colle et n'allez pas plus loin sur cette voie dangereuse. Cela, en utilisant PyArray_FromAny, vous donnera une vue des données sous-jacentes si possible et une copie sinon. Un exemple très simple (construire avec std = C++ 11 si vous êtes une personne honnête et bon, ou VS2013 si vous êtes un utilisateur de 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(); 
} 

Notez le argument true comme second paramètre à Py :: Constructeurs d'objets pour les objets "possédés"! An example of a cpython3 extension that uses the Numpy C API in combination with PyCXX with cmake for building. Le lien est à un commit spécifique parce que je songe à changer cette extension en utilisant Cython.