Discutamos un módulo de extensión que necesita manejar un puntero a una estructura de datos C, sin exponer ningún detalle interno de la estructura a Python. Las estructuras de datos opacas se pueden manejar fácilmente envolviéndolas dentro de objetos de cápsula como se muestra en el fragmento de código a continuación.
Código #1:
typedef struct Point { double x, y; } Point; extern double distance(Point *p1, Point *p2);
Consulte el artículo anterior para encontrar la función de distancia(): uso de códigos C en Python .
Código #2: El código dado es un código de extensión que envuelve la estructura y la función del Puntodistance()
usando cápsulas.
/* Destructor function for points */ static void del_Point(PyObject * obj) { free(PyCapsule_GetPointer(obj, "Point")); } /* Utility functions */ static Point * PyPoint_AsPoint(PyObject * obj) { return (Point *) PyCapsule_GetPointer(obj, "Point"); } static PyObject * PyPoint_FromPoint(Point * p, int must_free) { return PyCapsule_New(p, "Point", must_free ? del_Point : NULL); } /* Create a new Point object */ static PyObject * py_Point(PyObject * self, PyObject * args) { Point * p; double x, y; if (! PyArg_ParseTuple(args, "dd", &x, &y)) { return NULL; } p = (Point *) malloc(sizeof(Point)); p->x = x; p->y = y; return PyPoint_FromPoint(p, 1); } static PyObject * py_distance(PyObject * self, PyObject * args) { Point * p1, *p2; PyObject * py_p1, *py_p2; double result; if (! PyArg_ParseTuple(args, "OO", &py_p1, &py_p2)) { return NULL; } if (!(p1 = PyPoint_AsPoint(py_p1))) { return NULL; } if (!(p2 = PyPoint_AsPoint(py_p2))) { return NULL; } result = distance(p1, p2); return Py_BuildValue("d", result); }
Código #3: Usar la función anterior en Python
import sample pt1 = sample.Point(2, 3) pt2 = sample.Point(4, 5) print ("pt1 : ", pt1) print ("\npt2 : ", pt2) print ("Distance : ", sample.distance(p1, p2))
Producción :
pt1 : <capsule object "Point" at 0x1004ea330> pt2 : <capsule object "Point" at 0x1005d1db0> Distance : 2.8284271247461903
- Las cápsulas son similares a un puntero C escrito.
- Contienen un puntero genérico junto con un nombre de identificación y se pueden crear fácilmente usando la
PyCapsule_New()
función. PyCapsule_GetPointer()
La función se utiliza para extraer el puntero contenido dentro de una cápsula.- La recolección de basura y la gestión de la memoria es una parte complicada que preocupa a las cápsulas.
PyPoint_FromPoint()
La función acepta un argumento must_free que indica si la estructura Point * subyacente se recopilará cuando se destruya la cápsula.
Publicación traducida automáticamente
Artículo escrito por manikachandna97 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA