C API из модуля расширения в Python | Комплект 1
Предположим, что имеется модуль расширения C, который внутренне определяет множество полезных функций, которые можно экспортировать как общедоступный C API для использования в другом месте. Теперь, если мы хотим использовать эти функции внутри других модулей расширения. Затем важно знать, как связать их вместе, но сделать это с помощью компилятора / компоновщика C кажется чрезмерно сложным.
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.
//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 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
// 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; } |
Внимание компьютерщик! Укрепите свои основы с помощью базового курса программирования Python и изучите основы.
Для начала подготовьтесь к собеседованию. Расширьте свои концепции структур данных с помощью курса Python DS. А чтобы начать свое путешествие по машинному обучению, присоединяйтесь к курсу Машинное обучение - базовый уровень.