массив numpy 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; } 

Вот как я называю это из 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 

Что происходит: первая печать в порядке, значения правильные. Но когда я замышляю, что это не так; во второй печати я вижу очень странные значения, такие как 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); } 

2 Solutions collect form web for “массив numpy C api”

Ваш std::vector объект кажется локальным для этой функции. PyArray_SimpleNewFromData не делает копию данных, которые вы передаете. Он просто держит указатель. Итак, как только ваша функция py_integrate вернется, вектор будет освобожден. Печать работает в первый раз, потому что ничего еще не написано над освобожденной памятью, но к тому времени, как вы дошли до следующей печати, что-то еще использовало эту память, в результате чего значения были разными.

Вам нужно создать массив NumPy, которому принадлежит собственное пространство для хранения, а затем скопировать данные в него.

Альтернативно, выделите свой вектор в куче. Затем сохраните указатель на него в CObject . Предоставьте деструктор, который удаляет вектор. Затем взгляните на тип PyArrayObject на уровне C. Он имеет член PyObject * называемый base . Сохраните свой CObject . Затем, когда массив NumPy будет собран мусором, счетчик ссылок на этом базовом объекте будет уменьшен, и, предположив, что вы не взяли его копию в другом месте, ваш вектор будет удален благодаря деструктору, который вы предоставили.

Fixer-верхний

Вы забыли создать 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]) работает по назначению с указателем на вектор. Я знаю, что вектор перераспределяет область хранения, если вы его вырасти, поэтому не увеличивайте его размер после получения этого указателя, или он больше не будет действителен.

Вам нужно будет сделать копию вектора, так как вектор выйдет за пределы области действия, и память больше не будет использоваться к моменту, когда вам это понадобится в 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()); 
  • Wrap std :: вектор std :: векторов, C ++ SWIG Python
  • Итерация через искровой RDD
  • преобразование списка Python в числовой вектор R
  • python + maya: Повернуть ось Y вдоль вектора
  • Python - векторы скорости и ускорения в определенных точках
  • boost.python выставить функцию, которая возвращает вектор <MyClass>
  • Граница решения границы matplotlib
  • SWIG-упаковка C ++ для Python: перевод списка строк в вектор STL строк STL
  • Python - лучший язык программирования в мире.