Continuamos con el tema de cómo llamar a C / C ++ desde Python3 . Ahora usamos las bibliotecas cffi , pybind11 . El método a través de ctypes se discutió en un artículo anterior.
C
Una biblioteca de prueba para demostrar el trabajo con variables globales, estructuras y funciones con argumentos de varios tipos.
prueba.h
typedef struct test_st_s test_st_t; extern int a; extern double b; extern char c; int func_ret_int(int val); double func_ret_double(double val); char *func_ret_str(char *val); char func_many_args(int val1, double val2, char val3, short val4); test_st_t *func_ret_struct(test_st_t *test_st); struct test_st_s { int val1; double val2; char val3; };
prueba.c
#include <stdio.h> #include <stdlib.h> #include "test.h" int a = 5; double b = 5.12345; char c = 'X'; int func_ret_int(int val) { printf("C get func_ret_int: %d\n", val); return val; } double func_ret_double(double val) { printf("C get func_ret_double: %f\n", val); return val; } char * func_ret_str(char *val) { printf("C get func_ret_str: %s\n", val); return val; } char func_many_args(int val1, double val2, char val3, short val4) { printf("C get func_many_args: int - %d, double - %f, char - %c, short - %d\n", val1, val2, val3, val4); return val3; } test_st_t * func_ret_struct(test_st_t *test_st) { if (test_st) { printf("C get test_st: val1 - %d, val2 - %f, val3 - %c\n", test_st->val1, test_st->val2, test_st->val3); } return test_st; }
La biblioteca es exactamente la misma que en el artículo de ctypes .
CFFI
Esta es una biblioteca para trabajar exclusivamente con C. De la descripción de esta biblioteca:
Interactúa con casi cualquier código C de Python
Algo de esto casi se encontró.
Para el experimento, se utilizó la versión 1.12.3 , puede leer sobre esto aquí .
Un poco sobre esta biblioteca en 2 palabras, CFFI genera su enlace en la parte superior de nuestra biblioteca y la compila en una biblioteca con la que trabajaremos.
Instalación
pip3 instalar cffi
Asamblea
El script de compilación que recopilará el enlace alrededor de nuestra biblioteca.
build.py
import os import cffi if __name__ == "__main__": ffi = cffi.FFI()
Pitón
Un ejemplo de trabajo con C desde Python a través de CFFI :
from cffi import FFI import sys import time
Para trabajar con código C ++ , debe escribir un enlace en C para él. El artículo sobre el método a través de ctypes describe cómo hacer esto. Enlace a continuación.
Pros y contras de CFFI
Pros :
- sintaxis simple cuando se usa en Python
- no es necesario volver a compilar la biblioteca fuente
Contras :
pybind11
pybind11, por el contrario, está diseñado específicamente para trabajar con C ++ . La versión 2.3.0 se utilizó para el experimento, puede leer sobre esto aquí . Ella no recopila fuentes de C, así que las traduje a fuentes de C ++.
Instalación
pip3 instalar pybind11
Asamblea
Necesitamos escribir un script de compilación para nuestra biblioteca.
build.py
import pybind11 from distutils.core import setup, Extension ext_modules = [ Extension( '_test',
Lo ejecutamos:
python3 setup.py build --build-lib=./lib
C ++
En la fuente de la biblioteca necesita agregar:
namespace py = pybind11;
Pitón
Un ejemplo de trabajo con C desde Python a través de pybind11 :
import sys import time
Pros y contras de pybind11
Pros :
- sintaxis simple cuando se usa en Python
Contras :
- necesita editar fuentes C ++ o escribir un enlace para ellas
- es necesario recolectar la biblioteca necesaria de la fuente
El tiempo promedio de ejecución de la prueba en cada método con 1000 comienza:
- tipos: - 0.0004987692832946777 segundos ---
- CFFI: - 0.00038521790504455566 segundos ---
- pybind: - 0.0004547207355499268 segundos ---
+, - porque los resultados fueron ligeramente diferentes cada vez. Además, se dedicó tiempo a imprimir, que era demasiado flojo para apagarlo (tome este tiempo como una constante, porque será ~ igual en todas las pruebas). Pero aún así, hay una diferencia horaria en las llamadas a funciones y en obtener los resultados de ellas.
Referencias