Kami melanjutkan topik tentang cara memanggil C / C ++ dari Python3 . Sekarang kita menggunakan pustaka cffi , pybind11 . Metode melalui ctypes dibahas dalam artikel sebelumnya.
C
Pustaka uji untuk mendemonstrasikan bekerja dengan variabel global, struktur, dan fungsi dengan argumen dari berbagai jenis.
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; }
Perpustakaan persis sama dengan di artikel ctypes .
CFFI
Ini adalah perpustakaan untuk bekerja secara eksklusif dengan C. Dari deskripsi perpustakaan ini:
Berinteraksi dengan hampir semua kode C dari Python
Sebagian dari ini hampir ditemukan.
Untuk percobaan, versi 1.12.3 digunakan , Anda dapat membacanya di sini .
Sedikit tentang perpustakaan ini dalam 2 kata, CFFI menghasilkan pengikatannya di atas perpustakaan kami dan mengkompilasinya menjadi perpustakaan yang dengannya kami akan bekerja.
Instalasi
pip3 instal cffi
Majelis
Skrip pembuatan yang akan mengumpulkan ikatan di sekitar perpustakaan kami.
build.py
import os import cffi if __name__ == "__main__": ffi = cffi.FFI()
Python
Contoh bekerja dengan C dari Python melalui CFFI :
from cffi import FFI import sys import time
Untuk bekerja dengan kode C ++ , Anda harus menulis ikatan C untuknya. Artikel tentang metode melalui ctypes menjelaskan bagaimana melakukan ini. Tautan di bawah ini.
Pro dan Kontra CFFI
Pro :
- sintaksis sederhana ketika digunakan dalam Python
- tidak perlu mengkompilasi ulang pustaka sumber
Cons :
pybind11
pybind11, sebaliknya, dirancang khusus untuk bekerja dengan C ++ . Versi 2.3.0 digunakan untuk percobaan, Anda dapat membacanya di sini . Dia tidak mengumpulkan sumber C, jadi saya menerjemahkannya ke sumber C ++.
Instalasi
pip3 instal pybind11
Majelis
Kita perlu menulis skrip build untuk pustaka kita.
build.py
import pybind11 from distutils.core import setup, Extension ext_modules = [ Extension( '_test',
Kami melaksanakannya:
python3 setup.py build --build-lib=./lib
C ++
Di sumber perpustakaan Anda perlu menambahkan:
namespace py = pybind11;
Python
Contoh bekerja dengan C dari Python via pybind11 :
import sys import time
Pro dan kontra dari pybind11
Pro :
- sintaksis sederhana ketika digunakan dalam Python
Cons :
- Anda perlu mengedit sumber C ++ , atau menulis ikatan untuknya
- perlu untuk mengumpulkan perpustakaan yang diperlukan dari sumber
Waktu pelaksanaan pengujian rata-rata pada setiap metode dengan 1000 dimulai:
- ctypes: - 0,0004987692832946777 detik ---
- CFFI: - 0,00038521790504455566 detik ---
- pybind: - 0,0004547207355499268 detik ---
+, - karena hasilnya sedikit berbeda setiap kali. Plus, waktu dihabiskan untuk mencetak, yang terlalu malas untuk saya matikan (anggap waktu ini konstan, karena akan ~ sama di semua pengujian). Tapi tetap saja, ada perbedaan waktu dalam fungsi panggilan dan mendapatkan hasil dari mereka.
Referensi