所以使用 ctypes 去调用动态链接库非常方便,过程很简单:
- 1)通过 ctypes.CDLL 去加载动态库;
- 2)加载动态链接库之后会返回一个对象,我们上面起名为 py_lib;
- 3)然后直接通过 py_lib 调用里面的函数,但为了程序的健壮性,建议使用反射,确定调用的函数存在后才会调用;
我们以上就演示了如何通过 ctypes 模块来调用 Rust 编译生成的动态库 , 但显然目前还是远远不够的,比如说:
from ctypes import CDLLpy_lib = CDLL("../py_lib/target/debug/libpy_lib.dylib")square_root = py_lib.get_square_root(100)print(square_root) # 0100 的平方根是 10,但却返回了 0 。这是因为 ctypes 在解析返回值的时候默认是按照整型来解析的,但当前的函数返回的是浮点型,因此函数在调用之前需要显式地指定其返回值类型 。不过在这之前 , 我们需要先来看看 Python 类型和 Rust 类型之间的转换关系 。
数值类型使用 ctypes 调用动态链接库 , 主要是调用库里面使用 Rust 编写好的函数,但这些函数是需要参数的,还有返回值 。而不同语言的变量类型不同 , Python 不能直接往 Rust 编写的函数中传参,因此 ctypes 提供了大量的类,帮我们将 Python 的类型转成 Rust 的类型 。
与其说转成 Rust 的类型,倒不如说转成 C 的类型,因为 Rust 导出的函数要遵循 C 的调用约定 。下面来测试一下,首先编写 Rust 代码:
#[no_mangle]pub extern "C" fn add_u32(a: u32) -> u32 { a + 1}#[no_mangle]pub extern "C" fn add_isize(a: isize) -> isize { a + 1}#[no_mangle]pub extern "C" fn add_f32(a: f32) -> f32 { a + 1.}#[no_mangle]pub extern "C" fn add_f64(a: f64) -> f64 { a + 1.}#[no_mangle]pub extern "C" fn reverse_bool(a: bool) -> bool { !a}编译之后 Python 进行调用 。from ctypes import *py_lib = CDLL("../py_lib/target/debug/libpy_lib.dylib")print(py_lib.add_u32(123))"""124"""print(py_lib.add_isize(666))"""667"""try: print(py_lib.add_f32(3.14))except Exception as e: print(e)"""<class 'TypeError'>: Don't know how to convert parameter 1"""# 我们看到报错了,告诉我们不知道如何转化第 1 个参数# 因为 Python 的数据和 C 的数据不一样,所以不能直接传递# 但整数是个例外 , 除了整数,其它数据都需要使用 ctypes 包装一下# 另外整数最好也包装一下,因为不同整数之间 , 精度也有区别print(py_lib.add_f32(c_float(3.14)))"""1"""# 虽然没报错,但是结果不对 , 结果应该是 3.14 + 1 = 4.14,而不是 1# 因为 ctypes 调用函数时默认使用整型来解析,但该函数返回的不是整型# 需要告诉 ctypes,add_f32 函数返回的是 c_float,请按照 c_float 来解析py_lib.add_f32.restype = c_floatprint(py_lib.add_f32(c_float(3.14)))"""4.140000343322754"""# f32 和 f64 是不同的类型,占用的字节数也不一样# 所以 c_float 和 c_double 之间不可混用 , 虽然都是浮点数py_lib.add_f64.restype = c_doubleprint(py_lib.add_f64(c_double(3.14)))"""4.140000000000001"""py_lib.reverse_bool.restype = c_boolprint(py_lib.reverse_bool(c_bool(True)))print(py_lib.reverse_bool(c_bool(False)))"""FalseTrue"""不复杂,以上我们就实现了数值类型的传递 。字符类型字符类型有两种,一种是 ASCII 字符,本质上是个 u8;一种是 Unicode 字符,本质上是个 u32 。

文章插图
编写 Rust 代码:
#[no_mangle]pub extern "C" fn get_char(a: u8) -> u8 { a + 1}#[no_mangle]pub extern "C" fn get_unicode(a: u32) -> u32 { let chr = char::from_u32(a).unwrap(); if chr == '憨' { '批' as u32 } else { a }}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 你知道 Python 其实自带了小型数据库吗
- 解密Java连接MySQL的最佳实践:选择适合你的方式
- QQ如何用指纹解锁
- 怎么成为淘宝买菜的团长 如何申请成为淘宝买菜团长
- 如何制作三角形笔刷ps,ps该如何才可以画出三角形
- 在拼多多上如何修改评价,拼多多怎么修改评价等级
- cdr中应该如何画波浪线
- cdr2020如何合并打印,cdr该如何才可以进行打印
- 水泥路面起砂如何处理 水泥路面起砂如何处理视频
- 装修公司如何选 装修公司如何选好门店
