2

我想将 numpy 数组转换为 c++ 端的一些 double* 或 stl 向量。我实际上为此使用了 PyCXX,但我无法弄清楚访问数据的方法。

我目前能够像这样访问和返回数据缓冲区:

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

但我不知道该怎么办。我的最终目标是从中获得一个 gsl_vector。理想情况下,我不必重新复制内存。但也许问得太多了;)

4

1 回答 1

2

当我在寻找解决方案时,我只能找到其他人发布相同的、长期未回答的问题,我会在发现解决方案后发布解决方案。你的问题就是这样。

首先,强烈考虑使用 Cython 作为你的粘合剂,不要再沿着这条危险的道路前进。

顺便说一句,如果可能,使用 PyArray_FromAny 将为您提供底层数据的视图,否则为您提供副本。一个非常简单的例子(如果你是一个诚实善良的人,使用 -std=c++11 构建,如果你是 Windows 用户,则使用 VS2013 构建):

#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();
}

请注意 true 参数作为“拥有”对象的 Py::Object 构造函数的第二个参数! 使用 Numpy C API 结合 PyCXX 和 cmake 进行构建的 cpython3 扩展示例。 该链接指向特定的提交,因为我正在考虑将此扩展切换回使用 Cython。

于 2014-11-19T16:41:04.197 回答