Escribamos una función de extensión de C que pueda operar en conjuntos de datos contiguos, como podría ser creado por el módulo de array o bibliotecas como NumPy y esta función debe ser de propósito general y no específica para ninguna biblioteca de array.
El código debe usar Buffer Protocol para recibir y procesar arrays de manera portátil. El siguiente código es una función de extensión de C que recibe datos de array y llama a la avg(double *buf, int len)
función de este artículo: Uso de códigos C en Python .
Código #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); }
Código #2: Cómo funciona esta función de extensión
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]))
Producción :
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()
La función es la clave del código en el artículo.- Intenta obtener la información sobre la representación de la memoria en el objeto de Python arbitrario dado.
- Simplemente genera una excepción y devuelve -1, si no es posible obtener información (como es el caso de los objetos normales de Python).
- Las banderas especiales pasadas para
PyBuffer_GetBuffer()
dar pistas adicionales sobre el tipo de búfer de memoria que se solicita. - Como, PyBUF_ANY_CONTIGUOUS especifica que se requiere una región de memoria contigua.
Publicación traducida automáticamente
Artículo escrito por manikachandna97 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA