numpy数组C api

Rug*_*rra 8 c python numpy vector python-c-api

我有一个C++函数返回一个std :: vector,我想在python中使用它,所以我使用的是C numpy api:

static PyObject *
py_integrate(PyObject *self, PyObject *args){
    ...
    std::vector<double> integral;
    cpp_function(integral);  // This changes integral
    npy_intp size = {integral.size()};
    PyObject *out = PyArray_SimpleNewFromData(1, &size, NPY_DOUBLE, &(integral[0]));
    return out;
}
Run Code Online (Sandbox Code Playgroud)

这是我从python中调用它的方式:

import matplotlib.pyplot as plt

a = py_integrate(parameters)
print a
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(a)
print a
Run Code Online (Sandbox Code Playgroud)

会发生什么:第一次打印没问题,值是正确的.但是当我描绘a他们不是; 在第二打印我看到这样很奇怪的值1E-308 1E-308 ...0 0 0 ...为未初始化的内存.我不明白为什么第一次打印没问题.

部分解决方案(不工作):

static void DeleteVector(void *ptr)
{
    std::cout << "Delete" << std::endl;
    vector * v = static_cast<std::vector<double> * >(ptr);
    delete v;
    return;
}

static PyObject *
cppfunction(PyObject *self, PyObject *args)
{
    std::vector<double> *vector = new std::vector<double>();
    vector->push_back(1.);
    PyObject *py_integral = PyCObject_FromVoidPtr(vector, DeleteVector);
    npy_intp size = {vector->size()};
    PyArrayObject *out;
    ((PyArrayObject*) out)->base = py_integral;
    return (PyObject*)(out);
}
Run Code Online (Sandbox Code Playgroud)

kwa*_*ord 11

您的std::vector对象似乎是该功能的本地对象.PyArray_SimpleNewFromData不会复制您传递的数据.它只是一个指针.因此,一旦你的py_integrate函数返回,向量就会被释放.打印工作是第一次,因为还没有任何内容写入释放的内存,但是当你进入下一个打印时,其他东西已经使用了那个内存,导致值不同.

您需要创建一个拥有自己的存储空间的NumPy数组,然后将数据复制到其中.

或者,在堆上分配矢量.然后在CObject中存储指向它的指针.提供删除向量的析构函数.然后,看一下C级PyArrayObject类型.它有一个PyObject *叫做的成员base.存放在CObject那里.然后当NumPy数组被垃圾收集时,该基础对象的引用计数将递减,并且假设您没有在其他地方获取它的副本,由于您提供的析构函数,您的向量将被删除.

固定器,上

你忘了实际创建PyArray.试试这个:

(你没有发帖DeleteVector,所以我只能希望它是对的)

std::vector<double> *vector = new std::vector<double>();
vector->push_back(1.);
PyObject *py_integral = PyCObject_FromVoidPtr(vector, DeleteVector);
npy_intp size = {vector->size()};
PyObject *out = PyArray_SimpleNewFromData(1, &size, NPY_DOUBLE, &((*vector)[0]));
((PyArrayObject*) out)->base = py_integral;
return out;
Run Code Online (Sandbox Code Playgroud)

注意:我不是C++程序员,所以我只能假设它&((*vector)[0])与指向向量的指针一样工作.我知道如果你增长它,矢量会重新分配它的存储区域,所以在获得指针之后不要增加它的大小,否则它将不再有效.