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
# 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" );
}
|
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.
#include "Python.h"
#include "work.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct
{
Point *(*aspoint)(PyObject *);
PyObject *(*frompoint)(Point *, int );
} _PointAPIMethods;
#ifndef PYTHONSAMPLE_MODULE
static _PointAPIMethods *_point_api = 0;
|
Code #3 : Import the API table from “work”
static int import_sample( void )
{
_point_api = (_PointAPIMethods *) PyCapsule_Import( "work._point_api" , 0);
return (_point_api != NULL) ? 1 : 0;
}
#define PyPoint_AsPoint(obj) (_point_api->aspoint)(obj)
#define PyPoint_FromPoint(obj) (_point_api->frompoint)(obj)
#endif
#ifdef __cplusplus
}
#endif
|
_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
/ / pythonsample.c
/ / 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
};
|
Code #5 : Module function
PyMODINIT_FUNC
PyInit_sample( void )
{
PyObject *m;
PyObject *py_point_api;
m = PyModule_Create(&samplemodule);
if (m == NULL)
return NULL;
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;
}
|
Last Updated :
27 Mar, 2019
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...