Nous continuons le sujet de la façon d'appeler C / C ++ à partir de Python3 . Nous utilisons maintenant les bibliothèques cffi , pybind11 . La méthode par ctypes a été discutée dans un article précédent.
C
Une bibliothèque de tests pour montrer comment travailler avec des variables globales, des structures et des fonctions avec des arguments de différents types.
test.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; };
test.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 bibliothèque est exactement la même que dans l'article ctypes .
CFFI
Ceci est une bibliothèque pour travailler exclusivement avec C. D'après la description de cette bibliothèque:
Interagissez avec presque tous les codes C de Python
Une partie de cela a été presque trouvée.
Pour l'expérience, la version 1.12.3 a été utilisée , vous pouvez en lire plus ici .
Un peu sur cette bibliothèque en 2 mots, CFFI génère sa liaison au dessus de notre bibliothèque et la compile dans une bibliothèque avec laquelle nous travaillerons.
L'installation
pip3 installer cffi
Assemblage
Le script de construction qui collectera la liaison autour de notre bibliothèque.
build.py
import os import cffi if __name__ == "__main__": ffi = cffi.FFI()
Python
Un exemple de travail avec C de Python via CFFI :
from cffi import FFI import sys import time
Pour travailler avec du code C ++ , vous devez écrire une liaison C pour cela. L'article sur la méthode via ctypes décrit comment procéder. Lien ci-dessous.
Avantages et inconvénients de CFFI
Avantages :
- syntaxe simple lorsqu'elle est utilisée en Python
- pas besoin de recompiler la bibliothèque source
Inconvénients :
pybind11
pybind11, en revanche, est conçu spécifiquement pour travailler avec C ++ . La version 2.3.0 a été utilisée pour l'expérience, vous pouvez en lire plus ici . Elle ne collecte pas de sources C, donc je les ai traduites en sources C ++.
L'installation
pip3 installer pybind11
Assemblage
Nous devons écrire un script de construction pour notre bibliothèque.
build.py
import pybind11 from distutils.core import setup, Extension ext_modules = [ Extension( '_test',
Nous l'exécutons:
python3 setup.py build --build-lib=./lib
C ++
Dans la source de la bibliothèque, vous devez ajouter:
namespace py = pybind11;
Python
Un exemple de travail avec C depuis Python via pybind11 :
import sys import time
Avantages et inconvénients de pybind11
Avantages :
- syntaxe simple lorsqu'elle est utilisée en Python
Inconvénients :
- vous devez modifier les sources C ++ ou écrire une liaison pour elles
- il est nécessaire de collecter la bibliothèque nécessaire à partir de la source
Le temps d'exécution moyen des tests sur chaque méthode avec 1000 démarrages:
- ctypes: - 0,0004987692832946777 secondes ---
- CFFI: - 0,00038521790504455566 secondes ---
- pybind: - 0,0004547207355499268 secondes ---
+, - parce que les résultats étaient légèrement différents à chaque fois. De plus, j'ai passé du temps à imprimer, ce que j'étais trop paresseux pour désactiver (prenez ce temps comme une constante, car ce sera ~ le même dans tous les tests). Mais malgré tout, il y a une différence de temps entre les appels de fonction et l'obtention des résultats.
Les références