在 Python 和 Rust 之间传递整数的安全性

问题描述 投票:0回答:1

这安全吗?

假设我想从 Python 中调用一些 Rust 代码。假设我的

lib.rs
看起来像这样:

#[no_mangle]
pub extern fn add(left: i32, right: i32) -> i32 {
    return left+right;
}

假设我使用

ctypes
从 Python 调用这段代码,如下所示:

import ctypes

def rust_add(left, right):
    rust_lib = ctypes.CDLL("path/to/the/so/file")
    return rust_lib.add(left, right)

那么以上安全吗?

预期的障碍:整数溢出

输入溢出

即使是我——对 Rust 的掌握极其薄弱——也可以预见到一个问题是“整数溢出”。我想,如果 left

right
大于 2^32,就会导致不好的事情发生:Rust 要么会遇到运行时错误(最有可能),要么只会返回愚蠢的答案(最坏的情况下)。 Python 中的一些类型检查(也许使用 NumPy 的
uint32
)是否足以防止此问题?
工作中的溢出

这个更加阴险:假设我从 Python 中要求我的 Rust 函数添加 (2^32)-1 和 (2^32)-2。不应该立即发生溢出,但是一旦我们将两个数字加在一起就会发生溢出。据我了解,在遇到这样的溢出时,Rust 在调试模式下会出现恐慌,但在发布模式下会尽力坚持下去。

总结

除了彻底测试之外,是否有任何众所周知的实践可以解决在动态宽度语言(例如 Python)和固定宽度语言(例如 Rust)之间传递整数时出现的困难?
  • 除了
  • 整数溢出之外,在 Rust 和 Python 之间传递整数是否存在任何问题?
默认情况下,
python rust ctypes integer-overflow
1个回答
0
投票
会将整数参数和函数返回值转换为其

c_int
类型, 其大小取决于平台。超过此大小的值将被截断。如果
c_int
碰巧不是 32 位,这将导致 Rust 意义上的未定义行为(您最终会使用不正确的调用约定来调用 rust 函数)。在这种情况下,这可能不是您想要的。
因此我推荐以下Python代码:

def rust_add(left, right): rust_lib = ctypes.CDLL("path/to/the/so/file") rust_add = rust_lib.add rust_add.argtypes = [ctypes.c_int32, ctypes.c_int32] rust_add.restype = ctypes.c_int32 return rust_add(left, right)

这样,无论平台如何,
ctypes
都会将参数和返回类型转换为正确的整数类型。

它仍然会截断较大的整数,并为其他 python 类型抛出异常。如果您想以不同的方式处理这些情况,您必须自己做。
有关 
ctypes

如何处理类型转换的更多详细信息,我推荐他们出色的

文档

© www.soinside.com 2019 - 2024. All rights reserved.