Модуль расширения C с использованием Python
Написание простого модуля расширения C напрямую с использованием API расширений Python и никаких других инструментов. Создать ручной модуль расширения для простого кода на языке C несложно. Но сначала мы должны убедиться, что код C имеет правильный файл заголовка.
Code #1 :
#include <math.h> extern int gcd( int , int ); extern int in_mandel( double x0, double y0, int n); extern int divide( int a, int b, int *remainder); extern double avg( double *a, int n); typedef struct Point { double x, y; } Point; extern double distance(Point *p1, Point *p2); |
Заголовок соответствует библиотеке, которая была скомпилирована отдельно. Приведенный ниже код иллюстрирует основы написания функций расширения, исходя из этого предположения.
Code #2:
# include "Python.h" # include "sample.h" /* int gcd(int, int) */ static PyObject * py_gcd(PyObject * self, PyObject * args) { int x, y, result; if (! PyArg_ParseTuple(args, "ii" , &x, &y)) { return NULL; } result = gcd(x, y); return Py_BuildValue( "i" , result); } /* int divide(int, int, int *) */ static PyObject * py_divide(PyObject * self, PyObject * args) { int a, b, quotient, remainder; if (! PyArg_ParseTuple(args, "ii" , &a, &b)) { return NULL; } quotient = divide(a, b, &remainder); return Py_BuildValue( "(ii)" , quotient, remainder); } |
Код # 3: таблица и структура методов модуля
/* Module method table */ static PyMethodDef SampleMethods[] = { { "gcd" , py_gcd, METH_VARARGS, "Greatest common divisor" }, { "divide" , py_divide, METH_VARARGS, "Integer division" }, { NULL, NULL, 0, NULL} }; /* Module structure */ static struct PyModuleDef samplemodule = { PyModuleDef_HEAD_INIT, "sample" , /* name of module */ "A sample module" , /* Doc string (may be NULL) */ -1, /* Size of per-interpreter state or -1 */ SampleMethods /* Method table */ }; /* Module initialization function */ PyMODINIT_FUNC PyInit_sample( void ) { return PyModule_Create(&samplemodule); } |
Code #4: Creating a setup.py
python file for building the extension module.
# setup.py from distutils.core import setup, Extension setup(name = "sample" , ext_modules = [ Extension( "sample" , [ "pysample.c" ], include_dirs = [ "/some/dir" ], define_macros = [( "FOO" , "1" )], undef_macros = [ "BAR" ], library_dirs = [ "/usr/local/lib" ], libraries = [ "sample" ] ) ] ) |
Code #5: Now simply use python3 buildlib.py build_ext --inplace
, to build the resulting library.
bash% python3 setup.py build_ext --inplace running build_ext building "sample" extension gcc -fno-strict-aliasing -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -I/usr/local/include/python3.3m -c pysample.c -o build/temp.macosx-10.6-x86_64-3.3/pysample.o gcc -bundle -undefined dynamic_lookup build/temp.macosx-10.6-x86_64-3.3/pysample.o -L/usr/local/lib -lsample -o sample.so bash %
The above code will create a shared library called sample.so.
Code #6 :
import sample print ( "gcd = " , sample.gcd( 35 , 42 )) print ( "
distance : " , sample.divide( 42 , 8 )) |
Выход :
gcd = 7 расстояние = (5, 2)
«Расширение и встраивание интерпретатора Python» - это документация Python, с которой можно ознакомиться, прежде чем пытаться создать какое-либо расширение, написанное от руки.
В модулях расширения функции могут быть написаны, как показано во фрагменте кода ниже.
Code #4 :
static PyObject * py_func(PyObject * self , PyObject * args) { ... } |
- PyObject – C data type that represents any Python object. At a very high level, an extension function is a C function that receives a tuple of Python objects (in
PyObject *args
) and returns a new Python object as a result. The self argument to the function is unused for simple extension functions, but comes into play should you want to define new classes or object types in C. - The
PyArg_ParseTuple()
function is used to convert values from Python to a C representation. As input, it takes a format string that indicates the required values, such as “i” for integer and “d” for double, as well as the addresses of C variables in which to place the converted results. Py_BuildValue()
function is used to create Python objects from C data types. It also accepts a format code to indicate the desired type. In the extension functions, it is used to return results back to Python. One feature ofPy_BuildValue()
is that it can build more complicated kinds of objects, such as tuples and dictionaries.
Внимание компьютерщик! Укрепите свои основы с помощью базового курса программирования Python и изучите основы.
Для начала подготовьтесь к собеседованию. Расширьте свои концепции структур данных с помощью курса Python DS. А чтобы начать свое путешествие по машинному обучению, присоединяйтесь к курсу Машинное обучение - базовый уровень.