C API from Extension Module in Python | Set 1

Suppose given a C extension module that internally defines a variety of useful functions that can be exported as a public C API for use elsewhere. Now if we want to use these functions inside other extension modules. Then, it is important to know how to link them together but doing it with the C compiler/linker seems excessively complicated.

Code #1 : [C code] Point objects including some utility functions

filter_none

edit
close

play_arrow

link
brightness_4
code

# 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");
}

chevron_right


Now, the issue to deal with is how to handle the exportation of the PyPoint_AsPoint() and PyPoint_FromPoint() functions as an API that can be used by and can link to other extension modules. (For example – any other extensions also want to use the wrapped Point objects).

 
Code #2 : Introducing a new header file called Pythonsample.h for the work extension.

filter_none

edit
close

play_arrow

link
brightness_4
code

//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;

chevron_right


 
Code #3 : Import the API table from “work”

filter_none

edit
close

play_arrow

link
brightness_4
code

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

chevron_right


 
_PointAPIMethods table of function pointers is the most important feature as it will be initialized in the exporting module and found by importing modules. The code below shows how to change the original extension module to populate the table and export it.

Code #4 : Destructor and Utility Function

filter_none

edit
close

play_arrow

link
brightness_4
code

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

chevron_right


 
Code #5 : Module function

filter_none

edit
close

play_arrow

link
brightness_4
code

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

chevron_right




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.