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

  • Python: дифференцирование между векторами строк и столбцов
  • numpy: syntax / idiom для массива (n,) для массива (n, 1)?
  • Передача списка Python на вектор C ++ с использованием Boost.python
  • Как создать пустой вектор R для добавления новых элементов
  • Граница решения границы matplotlib
  • python + maya: Повернуть ось Y вдоль вектора
  • SWIG-обернутый вектор векторов (C ++ to python) - как распознать внутренний вектор как прокси-объект?
  • Как разбить вектор на столбцы - используя PySpark
  • 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()); 
    Python - лучший язык программирования в мире.