如何处理将 usize 传递给需要 uint32_t 的 C 函数?
How to handle passing usize to a C function that expects uint32_t?
我正在围绕 C 库编写 Rust 包装器。 C库提供了以下功能:
void lib_foo(const unsigned char *buf, uint32_t buf_len);
我创建了以下 extern
包装器:
fn lib_foo(buf: *const u8, buf_len: u32);
和以下高级包装器:
pub fn foo(buf: &[u8]) {
unsafe { lib_foo(buf.as_ptr(), buf.len() as u32) }
}
但是,从 usize
(buf.len()
的类型)到 u32
的转换可能会导致大小被截断。处理此问题的最佳方法是什么?
- 如果使用
lib_foo
对 read/write 块有意义,请将其包装在一个循环中,该循环处理 2**32 的块(以递增的偏移量),然后处理其余部分。在大多数情况下它会跳过循环,但在特殊情况下,它只会多次调用 lib_foo
- 如果
lib_foo
可以接受截断行为,请截断并以某种方式告诉用户
- 如果不是,大声抱怨 if len >= 2**32
首先,请使用 libc
类型的箱子。
即:extern fn lib_foo(buf: *const libc::c_uchar, buf_len: libc::uint32_t);
虽然略长,但会避免假设(unsigned char
映射到u8
)并自动翻译。
然后,进入高级包装器。
没有任何假设,最简单的解决方案是恐慌,并记录下来。
/// Calls `lib_foo`, ...
///
/// # Panics
///
/// If the size of the buffer is strictly greater than 2^32-1 bytes.
pub fn foo(buf: &[u8]) {
assert!(buf.len() <= (std::u32::MAX as usize));
unsafe { lib_foo(buf.as_ptr() as *const _, buf.len() as libc::uint32_t) }
}
然后,根据域的不同,可能会出现其他选项:
- 饱和度可能是一个选项(使用
std::cmp::min
)
- 重复调用可能是另一个
- ...
在任何情况下,如果用户可以观察到行为差异,文档。
我正在围绕 C 库编写 Rust 包装器。 C库提供了以下功能:
void lib_foo(const unsigned char *buf, uint32_t buf_len);
我创建了以下 extern
包装器:
fn lib_foo(buf: *const u8, buf_len: u32);
和以下高级包装器:
pub fn foo(buf: &[u8]) {
unsafe { lib_foo(buf.as_ptr(), buf.len() as u32) }
}
但是,从 usize
(buf.len()
的类型)到 u32
的转换可能会导致大小被截断。处理此问题的最佳方法是什么?
- 如果使用
lib_foo
对 read/write 块有意义,请将其包装在一个循环中,该循环处理 2**32 的块(以递增的偏移量),然后处理其余部分。在大多数情况下它会跳过循环,但在特殊情况下,它只会多次调用lib_foo
- 如果
lib_foo
可以接受截断行为,请截断并以某种方式告诉用户 - 如果不是,大声抱怨 if len >= 2**32
首先,请使用 libc
类型的箱子。
即:extern fn lib_foo(buf: *const libc::c_uchar, buf_len: libc::uint32_t);
虽然略长,但会避免假设(unsigned char
映射到u8
)并自动翻译。
然后,进入高级包装器。
没有任何假设,最简单的解决方案是恐慌,并记录下来。
/// Calls `lib_foo`, ...
///
/// # Panics
///
/// If the size of the buffer is strictly greater than 2^32-1 bytes.
pub fn foo(buf: &[u8]) {
assert!(buf.len() <= (std::u32::MAX as usize));
unsafe { lib_foo(buf.as_ptr() as *const _, buf.len() as libc::uint32_t) }
}
然后,根据域的不同,可能会出现其他选项:
- 饱和度可能是一个选项(使用
std::cmp::min
) - 重复调用可能是另一个
- ...
在任何情况下,如果用户可以观察到行为差异,文档。