C API из модуля расширения в Python | Комплект 1
Предположим, что имеется модуль расширения C, который внутренне определяет множество полезных функций, которые можно экспортировать как общедоступный C API для использования в другом месте. Теперь, если мы хотим использовать эти функции внутри других модулей расширения. Затем важно знать, как связать их вместе, но сделать это с помощью компилятора / компоновщика C кажется чрезмерно сложным.
Code #1 : [C code] Point objects including some utility functions
# Destructor function for pointsstatic 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.
//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; |
Код № 3: Импортировать таблицу API из «работы»
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 |
Таблица указателей функций _PointAPIMethods является наиболее важной функцией, поскольку она будет инициализирована в модуле экспорта и найдена при импорте модулей. В приведенном ниже коде показано, как изменить исходный модуль расширения для заполнения таблицы и ее экспорта.
Code #4 : Destructor and Utility Function
// pythonsample.c# include "Python.h"# define PYTHONSAMPLE_MODULE# include "pythonsample.h" // Destructor function for points static void del_Point(PyObject * obj){ printf("Deleting point
"); free(PyCapsule_GetPointer(obj, "Point"));} // Utility functionsstatic 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
// Module initialization function PyMODINIT_FUNCPyInit_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;} |
Внимание компьютерщик! Укрепите свои основы с помощью базового курса программирования Python и изучите основы.
Для начала подготовьтесь к собеседованию. Расширьте свои концепции структур данных с помощью курса Python DS. А чтобы начать свое путешествие по машинному обучению, присоединяйтесь к курсу Машинное обучение - базовый уровень.