Wir setzen das Thema fort, wie C / C ++ von Python3 aufgerufen wird . Jetzt verwenden wir die cffi , pybind11 Bibliotheken . Die Methode durch ctypes wurde in einem früheren Artikel diskutiert.
C.
Eine Testbibliothek zur Demonstration der Arbeit mit globalen Variablen, Strukturen und Funktionen mit Argumenten verschiedener Typen.
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; }
Die Bibliothek ist genau die gleiche wie im Artikel ctypes .
CFFI
Dies ist eine Bibliothek für die ausschließliche Arbeit mit C. Aus der Beschreibung dieser Bibliothek:
Interagiere mit fast jedem C-Code aus Python
Einiges davon wurde fast gefunden.
Für das Experiment wurde Version 1.12.3 verwendet , darüber können Sie hier lesen.
Ein wenig über diese Bibliothek in zwei Worten: CFFI generiert seine Bindung über unserer Bibliothek und kompiliert sie zu einer Bibliothek, mit der wir arbeiten werden.
Installation
pip3 installiere cffi
Montage
Das Build-Skript, das die Bindung um unsere Bibliothek sammelt.
build.py
import os import cffi if __name__ == "__main__": ffi = cffi.FFI()
Python
Ein Beispiel für die Arbeit mit C von Python über CFFI :
from cffi import FFI import sys import time
Um mit C ++ - Code arbeiten zu können, müssen Sie eine C- Bindung dafür schreiben. Der Artikel über die Methode durch ctypes beschreibt, wie dies getan wird. Link unten.
Vor- und Nachteile von CFFI
Vorteile :
- einfache Syntax bei Verwendung in Python
- Die Quellbibliothek muss nicht neu kompiliert werden
Nachteile :
pybind11
Im Gegensatz dazu wurde pybind11 speziell für die Arbeit mit C ++ entwickelt . Für das Experiment wurde Version 2.3.0 verwendet, darüber können Sie hier lesen. Sie sammelt keine C-Quellen, deshalb habe ich sie in C ++ - Quellen übersetzt.
Installation
pip3 installiere pybind11
Montage
Wir müssen ein Build-Skript für unsere Bibliothek schreiben.
build.py
import pybind11 from distutils.core import setup, Extension ext_modules = [ Extension( '_test',
Wir führen es aus:
python3 setup.py build --build-lib=./lib
C ++
In der Bibliotheksquelle müssen Sie Folgendes hinzufügen:
namespace py = pybind11;
Python
Ein Beispiel für die Arbeit mit C aus Python über pybind11 :
import sys import time
Vor- und Nachteile von pybind11
Vorteile :
- einfache Syntax bei Verwendung in Python
Nachteile :
- Sie müssen C ++ - Quellen bearbeiten oder eine Bindung für sie schreiben
- Es ist notwendig, die erforderliche Bibliothek aus der Quelle zu sammeln
Die durchschnittliche Testausführungszeit für jede Methode mit 1000 Starts:
- ctypes: - 0,0004987692832946777 Sekunden ---
- CFFI: - 0,00038521790504455566 Sekunden ---
- pybind: - 0,0004547207355499268 Sekunden ---
+, - weil die Ergebnisse jedes Mal leicht unterschiedlich waren. Außerdem wurde Zeit für das Drucken aufgewendet, was ich zu faul war, um es auszuschalten (nehmen Sie diese Zeit als Konstante, da sie in allen Tests gleich ist). Trotzdem gibt es einen Zeitunterschied zwischen den Funktionsaufrufen und dem Abrufen der Ergebnisse.
Referenzen