8

我有一个返回 std::vector 的 C++ 函数,我想在 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;
}

这是我从 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

发生的情况是:第一次打印没问题,值是正确的。但是当我绘制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);
}
4

2 回答 2

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;

注意:我不是 C++ 程序员,所以我只能假设&((*vector)[0])使用指向向量的指针可以按预期工作。我确实知道如果你增加它,向量会重新分配它的存储区域,所以在得到那个指针后不要增加它的大小,否则它将不再有效。

于 2010-05-27T21:18:50.483 回答
0

您将需要制作向量的副本,因为向量将超出范围,并且当您在 Python 中需要它时,内存将不再可用(如 kwatford 所述)。

制作所需的 Numpy 数组的一种方法(通过复制数据)是:

PyObject *out = nullptr;

std::vector<double> *vector = new std::vector<double>();
vector->push_back(1.);

npy_intp size = {vector.size()};

out = PyArray_SimpleNew(1, &size, NPY_DOUBLE);

memcpy(PyArray_DATA((PyArrayObject *) out), vector.data(), vector.size());
于 2014-04-17T18:00:17.457 回答