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 :

filter_none

edit
close

play_arrow

link
brightness_4
code

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

chevron_right


Code #2 : How this extension function works

filter_none

edit
close

play_arrow

link
brightness_4
code

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]))

chevron_right


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
  • PyBuffer_GetBuffer() function is the key to the code in the article.
  • It tries to obtain the information about the memory representation in the given arbitrary Python object.
  • It simply raises an exception and returns -1, if it is not possible to obtain information (as is the case with normal Python objects).
  • The special flags passed to PyBuffer_GetBuffer() give additional hints about the kind of memory buffer that is requested.
  • As, PyBUF_ANY_CONTIGUOUS specifies that a contiguous region of memory is required.


My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.




Article Tags :

Be the First to upvote.


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.