我们继续讨论如何从Python3调用C / C ++的主题 。 现在我们使用cffi , pybind11库 。 在上一篇文章中讨论了通过ctypes的方法。
ç
一个测试库,用于演示如何使用带有各种类型参数的全局变量,结构和函数。
测试
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; };
测试
#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; }
该库与ctypes文章中的库完全相同。
CFFI
这是专门用于C语言的库。 从该库的描述中:
与Python中几乎所有的C代码进行交互
其中一些几乎被发现。
对于实验, 使用1.12.3版本,您可以在此处阅读有关内容。
仅用 2个词就可以了解这个库, CFFI在我们的库顶部生成其绑定 , 并将其编译为一个我们可以使用的库。
安装方式
pip3安装cffi
组装方式
构建脚本将收集我们库中的绑定。
build.py
import os import cffi if __name__ == "__main__": ffi = cffi.FFI()
巨蟒
一个通过Python通过CFFI使用C的 示例 :
from cffi import FFI import sys import time
要使用C ++代码,您需要为其编写C绑定。 有关通过ctypes方法的文章介绍了如何执行此操作。 链接下面。
CFFI的优缺点
优点 :
缺点 :
pybind11
相比之下, pybind11是专门为使用C ++设计的 。 实验使用2.3.0版,您可以在此处阅读有关内容。 她没有收集C源代码,所以我将它们翻译成C ++源代码。
安装方式
pip3安装pybind11
组装方式
我们需要为我们的库编写一个构建脚本。
build.py
import pybind11 from distutils.core import setup, Extension ext_modules = [ Extension( '_test',
我们执行它:
python3 setup.py build --build-lib=./lib
C ++
在库源中,您需要添加:
namespace py = pybind11;
巨蟒
一个通过pybind11从Python使用C的 示例 :
import sys import time
pybind11的优缺点
优点 :
缺点 :
- 您需要编辑C ++源,或为它们编写绑定
- 有必要从源头收集必要的库
每个方法从1000开始的平均测试执行时间为:
- ctypes:-0.0004987692832946777秒-
- CFFI:-0.00038521790504455566秒-
- pybind:-0.0004547207355499268秒-
+,-,因为每次结果都略有不同。 另外,我花了很多时间在打印上,我懒得关闭它(把这个时间当作常数,因为在所有测试中都一样)。 但是,函数调用和从中获取结果仍然存在时间差异。
参考文献