numpy array C api
NickName:Ruggero Turra Ask DateTime:2010-05-28T04:53:25

numpy array C api

I have a C++ function returning a std::vector and I want to use it in python, so I'm using the 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;
}

Here's how I call it from 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

What happens is: The first print is ok, the values are correct. But when I plot a they are not; in the second print I see very strange values like 1E-308 1E-308 ... or 0 0 0 ... as an uninitialized memory. I don't understand why the first print is ok.

Partial solution (not working):

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

Copyright Notice:Content Author:「Ruggero Turra」,Reproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/2924827/numpy-array-c-api

Answers
kenm 2010-05-27T21:18:50

Your std::vector object appears to be local to that function. PyArray_SimpleNewFromData does not make a copy of the data you pass it. It just keeps a pointer. So once your py_integrate function returns, the vector is deallocated. The print works the first time because nothing has written over the freed memory yet, but by the time you get to the next print, something else has used that memory, causing the values to be different.\n\nYou need to make a NumPy array that owns its own storage space and then copy the data into it. \n\nAlternatively, allocate your vector on the heap. Then store a pointer to it in a CObject. Provide a destructor that deletes the vector. Then, take a look at the C-level PyArrayObject type. It has a PyObject * member called base. Store your CObject there. Then when the NumPy array is garbage collected, the reference count on this base object will be decremented, and assuming you haven't taken a copy of it elsewhere, your vector will be deleted thanks to the destructor you provided.\n\nFixer-upper\n\nYou forgot to actually create the PyArray. Try this:\n\n(You didn't post DeleteVector, so I can only hope that it's right)\n\nstd::vector<double> *vector = new std::vector<double>();\nvector->push_back(1.);\nPyObject *py_integral = PyCObject_FromVoidPtr(vector, DeleteVector);\nnpy_intp size = {vector->size()};\nPyObject *out = PyArray_SimpleNewFromData(1, &size, NPY_DOUBLE, &((*vector)[0]));\n((PyArrayObject*) out)->base = py_integral;\nreturn out;\n\n\nNote: I'm not a C++ programmer, so I can only assume that &((*vector)[0]) works as intended with a pointer to a vector. I do know that the vector reallocate its storage area if you grow it, so don't increase its size after getting that pointer or it won't be valid anymore. ",


More about “numpy array C api” related questions

Coerce a numpy array scalar to a particular C type using numpy C API

I have a PyObject* representing a numpy scalar array and I would like to check whether I can coerce the value to a float and then, if so, pull out a C float. I've been through the numpy C api docs in

Show Detail

Using numpy C API with ctypes

I want to use numpy C array api (https://numpy.org/doc/stable/reference/c-api/array.html) using ctypes python library. Similarly to how I can use python c api with ctypes. For example, I can refere...

Show Detail

Reversing axis in Numpy array using C-API

I am using the Python C-API to wrap some C++ code as a Python package. In the end, I have to reverse an axis in a numpy array, i.e. doing x = x[:, ::-1] Is there some way of doing this using the ...

Show Detail

Trouble with Numpy C API

Code (based on Numpy C-Api example gives a SegFault. The link to the tutorial they were following is dead, and I haven't found a good tutorial): #include &lt;Python.h&gt; #define NPY_NO_DEPRECATE...

Show Detail

Create an Array from the Python C API without numpy

Is it possible to create a Python Array in C using the C-API? If so how do I do this? Is arraymodule.c the right place to be looking in the CPython source? If I was using numpy I'd do this https://

Show Detail

Binding C array to Numpy array without copying

I am writing a Python class that will wrap a C module containing a C struct. I am using the Cython language (a super-set language of Python and C). The C struct is malloc'd in the constructor and

Show Detail

How does import_array in numpy C API work?

I am trying to convert a c-style array in c++ to a numpy array and ran into problems when trying to use the "PyArray_SimpleNewFromData" function. It turns out I need to call import_array() Thoug...

Show Detail

creating numpy array in c extension segfaults

I'm just trying to start off by creating a numpy array before I even start to write my extension. Here is a super simple program: #include &lt;stdio.h&gt; #include &lt;iostream&gt; #include "Pytho...

Show Detail

Accessing numpy array data in C (for numpy 1.7+)

Following examples and the numpy C-API (http://docs.scipy.org/doc/numpy/reference/c-api.html), I'm trying to access numpy array data in cpp, like this: #include &lt;Python.h&gt; #include &lt;frame...

Show Detail

What is the corresponding C-api name of the following numpy function in Python

I wanna write a C extension lib for Python, aiming to replace Python code with C. and the Python codes has several lines like below: import numpy as np a = np.array([1,3,12,0.43,234,-3,-4]) b = a[...

Show Detail