Supongamos que se le da un módulo de extensión de C que define internamente una variedad de funciones útiles que se pueden exportar como una API de C pública para usar en otros lugares. Ahora si queremos usar estas funciones dentro de otros módulos de extensión. Entonces, es importante saber cómo enlazarlos entre sí pero hacerlo con el compilador/enlazador de C parece excesivamente complicado.
Código #1: [Código C] Objetos de punto que incluyen algunas funciones de utilidad
# Destructor function for points static void del_Point(PyObject *obj) { free(PyCapsule_GetPointer(obj, "Point")); } static PyObject *PyPoint_FromPoint(Point *p, int must_free) { return PyCapsule_New(p, "Point", must_free ? del_Point : NULL); } # Utility functions static Point *PyPoint_AsPoint(PyObject *obj) { return (Point *) PyCapsule_GetPointer(obj, "Point"); }
Ahora, el problema a tratar es cómo manejar la exportación de las funciones PyPoint_AsPoint()
y PyPoint_FromPoint()
como una API que puede ser utilizada por otros módulos de extensión y puede vincularse a ellos. ( Por ejemplo , cualquier otra extensión también quiere usar los objetos Point envueltos).
Código #2: Presentamos un nuevo archivo de encabezado llamado Pythonsample.h
para la work
extensión.
//pythonsample.h #include "Python.h" #include "work.h" #ifdef __cplusplus extern "C" { #endif // Public API Table typedef struct { Point *(*aspoint)(PyObject *); PyObject *(*frompoint)(Point *, int); } _PointAPIMethods; #ifndef PYTHONSAMPLE_MODULE /* Method table in external module */ static _PointAPIMethods *_point_api = 0;
Código #3: Importar la tabla API desde «trabajo»
static int import_sample(void) { _point_api = (_PointAPIMethods *) PyCapsule_Import("work._point_api", 0); return (_point_api != NULL) ? 1 : 0; } /* Macros to implement the programming interface */ #define PyPoint_AsPoint(obj) (_point_api->aspoint)(obj) #define PyPoint_FromPoint(obj) (_point_api->frompoint)(obj) #endif #ifdef __cplusplus } #endif
La tabla de punteros de función _PointAPIMethods es la característica más importante, ya que se inicializará en el módulo de exportación y se encontrará en los módulos de importación. El siguiente código muestra cómo cambiar el módulo de extensión original para completar la tabla y exportarla.
Código #4: Destructor y Función de Utilidad
// pythonsample.c # include "Python.h" # define PYTHONSAMPLE_MODULE # include "pythonsample.h" // Destructor function for points static void del_Point(PyObject * obj) { printf("Deleting point\n"); 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 free) { return PyCapsule_New(p, "Point", free ? del_Point : NULL); } static _PointAPIMethods _point_api = { PyPoint_AsPoint, PyPoint_FromPoint };
Código #5: función del módulo
// Module initialization function PyMODINIT_FUNC PyInit_sample(void) { PyObject *m; PyObject *py_point_api; m = PyModule_Create(&samplemodule); if (m == NULL) return NULL; // Add the Point C API functions py_point_api = PyCapsule_New((void *) &_point_api, "work._point_api", NULL); if (py_point_api) { PyModule_AddObject(m, "_point_api", py_point_api); } return m; }
Publicación traducida automáticamente
Artículo escrito por manikachandna97 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA