Requisito previo: cómo llamar a una función C en Python
Analicemos el problema de acceder al código C desde Python. Como es muy evidente, muchas de las bibliotecas integradas de Python están escritas en C. Por lo tanto, acceder a C es una parte muy importante para hacer que Python se comunique con las bibliotecas existentes. Hay una extensa API de programación C que proporciona Python, pero hay muchas diferentes para tratar con C.
Código #1: [ work.c
] C-Code que estamos tratando.
#include <math.h> int gcd(int x, int y) { int g = y; while (x > 0) { g = x; x = y % x; y = g; } return g; } int divide(int a, int b, int * remainder) { int quot = a / b; *remainder = a % b; return quot; } double avg(double * a, int n) { int i; double total = 0.0; for (i = 0; i < n; i++) { total += a[i]; } return total / n; } typedef struct Point { double x, y; } Point; double distance(Point * p1, Point * p2) { return hypot(p1->x - p2->x, p1->y - p2->y); }
El código anterior tiene diferentes características de programación C.
gcd()
divide(): devuelve varios valores, uno a través de un argumento de puntero
avg(): realiza una reducción de datos en una array C
Punto y distancia(): involucra estructuras C.
Supongamos que el código anterior se encuentra en un archivo llamado work.c y se ha compilado en una biblioteca libsample que se puede vincular a otro código C. Ahora, tenemos varias funciones de C que se han compilado en una biblioteca compartida. Por lo tanto, llamamos a las funciones completamente desde Python sin tener que escribir código C adicional o usar una herramienta de extensión de terceros.
Uso de ctypes: los ctypes
de Python entrarán en juego, pero asegúrese de que el código C, que se va a convertir, se haya compilado en una biblioteca compartida que sea compatible con el intérprete de Python (por ejemplo, la misma arquitectura, tamaño de palabra, compilador, etc.) .
Además, el archivo libsample.so se ha colocado en el mismo directorio que el archivo work.py
. Entendamos work.py
ahora.
Código n.º 2: módulo de Python que envuelve la biblioteca resultante para acceder a ella
# work.py import ctypes import os # locating the 'libsample.so' file in the # same directory as this file _file = 'libsample.so' _path = os.path.join(*(os.path.split(__file__)[:-1] + (_file, ))) _mod = ctypes.cdll.LoadLibrary(_path)
Código #3: Código de acceso
# int gcd(int, int) gcd = _mod.gcd gcd.argtypes = (ctypes.c_int, ctypes.c_int) gcd.restype = ctypes.c_int # int divide(int, int, int *) _divide = _mod.divide _divide.argtypes = (ctypes.c_int, ctypes.c_int, ctypes.POINTER(ctypes.c_int)) _divide.restype = ctypes.c_int def divide(x, y): rem = ctypes.c_int() quot = _divide(x, y, rem) return quot, rem.value # void avg(double *, int n) # Define a special type for the 'double *' argument class DoubleArrayType: def from_param(self, param): typename = type(param).__name__ if hasattr(self, 'from_' + typename): return getattr(self, 'from_' + typename)(param) elif isinstance(param, ctypes.Array): return param else: raise TypeError("Can't convert % s" % typename) # Cast from array.array objects def from_array(self, param): if param.typecode != 'd': raise TypeError('must be an array of doubles') ptr, _ = param.buffer_info() return ctypes.cast(ptr, ctypes.POINTER(ctypes.c_double)) # Cast from lists / tuples def from_list(self, param): val = ((ctypes.c_double)*len(param))(*param) return val from_tuple = from_list # Cast from a numpy array def from_ndarray(self, param): return param.ctypes.data_as(ctypes.POINTER(ctypes.c_double)) DoubleArray = DoubleArrayType() _avg = _mod.avg _avg.argtypes = (DoubleArray, ctypes.c_int) _avg.restype = ctypes.c_double def avg(values): return _avg(values, len(values)) # struct Point { } class Point(ctypes.Structure): _fields_ = [('x', ctypes.c_double), ('y', ctypes.c_double)] # double distance(Point *, Point *) distance = _mod.distance distance.argtypes = (ctypes.POINTER(Point), ctypes.POINTER(Point)) distance.restype = ctypes.c_double
Ahora, uno puede cargar fácilmente el módulo y usar las funciones C resultantes. Vea la siguiente parte: uso de códigos C en Python | conjunto 2 .
Publicación traducida automáticamente
Artículo escrito por manikachandna97 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA