关于如何从Python3调用C / C ++的系列文章中的最后一篇文章,通过所有已知的方法进行了介绍。 这次我得加油 。 下文介绍了这些内容。
ç
我以测试库的相同示例为基础,并使其成为特定方法的变体。 一个测试库,用于演示如何使用带有各种类型参数的全局变量,结构和函数。
test.c:
#include "test.hpp" 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; } object func_ret_str(char *val) { printf("C get func_ret_str: %s\n", val); return object(string(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; }
test.h:
using namespace boost::python; using namespace std; #ifdef __cplusplus extern "C" { #endif typedef struct test_st_s test_st_t; typedef char * char_p; extern int a; extern double b; extern char c; int func_ret_int(int val); double func_ret_double(double val); object 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; }; #ifdef __cplusplus } #endif
如何编译:
g++ -g -fPIC -I/usr/include/python3.6 -I./src/c -o ./objs/test.o -c ./src/c/test.cpp g++ -fPIC -g -shared -o ./lib/_test.so ./objs/test.o -lboost_python3
源代码编译成一个动态库。
python boost与pybind11的用法相似,您还需要描述python将看到的功能。 但我认为,提振更为庞大和复杂。 例如:
def("func_ret_struct", &func_ret_struct, return_value_policy<reference_existing_object>());
func_ret_struct函数将指向结构的指针作为参数,并返回相同的指针。 为此,您需要指定返回对象的规则return_value_policy <reference_existing_object>() 。 reference_existing_objec说返回的对象已经存在。 如果指定manage_new_object,则意味着我们正在返回一个新对象。 在这种情况下,这样的脚本将在垃圾回收器上陷入分段错误 :
test_st = _test.test_st_t() ret = _test.func_ret_struct(test_st)
因为垃圾收集器将首先清除test_st包含的数据,然后再清除ret对象包含的数据。 其中包含与test_st包含的数据相同的数据,但已被清除。
在这种情况下,如何描述这样的功能(不深入)很有趣?:
test_st_t * func_ret_struct(test_st_t *test_st) { if (test_st) { return test_st; } else { return (test_st_t *) malloc(sizeof(test_st_t)); } }
这样的函数既可以返回现有对象,也可以返回现有对象。
我也有这样的功能的问题:
char * func_ret_str(char *val) { return val; }
据我了解,您无法在boost中从python获得指向标准数据类型的指针。 只能在struct , class和union上使用 。 如果有人知道开悟的方法。
巨蟒
对于python,该模块变为本机。
main.py:
提升的利弊
优点 :
缺点 :
- 您需要编辑C ++源,或为它们编写绑定
- 单靠提升并不容易
像往常一样,该代码试图清晰地注释。
每个方法从1000开始的平均测试执行时间为:
- ctypes:-0.0004987692832946777秒-
- CFFI:-0.00038521790504455566秒-
- pybind:-0.0004547207355499268秒-
- C API:-0.0003561973571777344秒-
- 提升:-0.00037789344787597656秒-
参考文献