C API del módulo de extensión en Python | Serie 1

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.hpara la workextensió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

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *