Open In App

Python | Extension function operating on Arrays

Let’s write a C extension function that can operate on contiguous arrays of data, as might be created by the array module or libraries like NumPy and this function should be general purpose and not specific to any one array library.

The code should use Buffer Protocol to receive and process arrays in a portable manner. The code below is a C extension function that receives array data and calls the avg(double *buf, int len) function from this article – Using C codes in Python.

Code #1 :




/* Call double avg(double *, int) */
static PyObject *py_avg(PyObject *self, PyObject *args)
{
    PyObject *bufobj;
    Py_buffer view;
    double result;
    /* Get the passed Python object */
    if (!PyArg_ParseTuple(args, "O", &bufobj))
    {
        return NULL;
    }
  
    /* Attempt to extract buffer information from it */
  
    if (PyObject_GetBuffer(bufobj, &view,
                           PyBUF_ANY_CONTIGUOUS | PyBUF_FORMAT) == -1)
    {
        return NULL;
    }
  
    if (view.ndim != 1)
    {
        PyErr_SetString(PyExc_TypeError, "Expected a 1-dimensional array");
        PyBuffer_Release(&view);
        return NULL;
    }
  
    /* Check the type of items in the array */
    if (strcmp(view.format, "d") != 0)
    {
        PyErr_SetString(PyExc_TypeError, "Expected an array of doubles");
        PyBuffer_Release(&view);
        return NULL;
    }
  
    /* Pass the raw buffer and size to the C function */
    result = avg(view.buf, view.shape[0]);
  
    /* Indicate we're done working with the buffer */
    PyBuffer_Release(&view);
    return Py_BuildValue("d", result);
}

Code #2 : How this extension function works




import array
  
print("Average : ", avg(array.array('d', [1, 2, 3])))
  
import numpy
print("Average numpy array : ", avg(numpy.array([1.0, 2.0, 3.0])))
print ("Average list : \n", avg([1, 2, 3]))

Output :

Average : 2.0

Average numpy array : 2.0
Average list : 
Traceback (most recent call last):
File "", line 1, in 
TypeError: 'list' does not support the buffer interface

Article Tags :