在 Rust 中将二维字节数组传递给 C
Pass 2D array of bytes to C in Rust
我用 C 写了一个函数,签名如下:
write_stuff(char **pages, uint32 page_count);
pages
将是一个包含 128 个元素的数组,每个元素要么为 NULL,要么指向一个 8192 字节的 char 数组。因此,一组具有固定已知大小的数组。
我需要在 Rust 中填充数组并将它们传递给 C 函数。当我使用 bindgen 生成 Rust 签名时,它会生成:
extern "C" {
pub fn write_stuff(pages: *mut *mut ::std::os::raw::c_char, page_count: u32,);
}
现在,我如何在 Rust 中声明一个我可以填充并传递给这个函数的变量?
我试过这个:
let mut pages = [Option <[u8; 8192]>; 128];
但它无法编译。
这编译:
type MyPage = Option<[u8; 8192]>;
let myarray: [MyPage; 128] = [None; 128];
但我不清楚它是否会以正确的格式存储数据,或者如何适当地转换它:
let pages: *mut *mut ::std::os::raw::c_char = myarray.as_mut_ptr() as // what goes here?;
我相信您正在寻找的 Rust 类型是 &[Option<&[u8; 8192]>]
。
C 版本使用双指针,所以你需要确保内部类型是一个引用。 Option<&T>
表明引用可以为空,并且 null pointer optimization 保证它与 T
.
具有相同的大小
我已经测试过下面的代码可以正常工作,
但我不是 100% 确定这种类型转换是合理的
所以我会在生产代码中小心使用它。
生锈 main.rs
#[link(name = "mylib")]
extern "C" {
pub fn write_stuff(pages: *mut *mut ::std::os::raw::c_char, page_count: u32);
}
pub fn write_stuff_rust(pages: &[Option<&[u8; 8192]>]) {
unsafe { write_stuff(pages.as_ptr() as *mut _, pages.len() as u32) }
}
fn main() {
let page1: [u8; 8192] = [b'a'; 8192];
let page3: [u8; 8192] = [b'b'; 8192];
let page4: [u8; 8192] = [b'c'; 8192];
let page7: [u8; 8192] = [b'd'; 8192];
let pages: Vec<Option<&[u8; 8192]>> = vec![
Some(&page1),
None,
Some(&page3),
Some(&page4),
None,
None,
Some(&page7),
];
write_stuff_rust(&pages);
}
C mylib.c
#include <stdio.h>
#include <stdint.h>
void write_stuff(char **pages, uint32_t page_count) {
for (uint32_t i = 0; i < page_count; i++) {
printf("%d=%p\n", i, pages[i]);
if (pages[i]) {
for (size_t j = 0; j < 8192; j++) {
putchar(pages[i][j]);
}
putchar('\n');
} else {
puts("<empty>");
}
}
}
我用 C 写了一个函数,签名如下:
write_stuff(char **pages, uint32 page_count);
pages
将是一个包含 128 个元素的数组,每个元素要么为 NULL,要么指向一个 8192 字节的 char 数组。因此,一组具有固定已知大小的数组。
我需要在 Rust 中填充数组并将它们传递给 C 函数。当我使用 bindgen 生成 Rust 签名时,它会生成:
extern "C" {
pub fn write_stuff(pages: *mut *mut ::std::os::raw::c_char, page_count: u32,);
}
现在,我如何在 Rust 中声明一个我可以填充并传递给这个函数的变量?
我试过这个:
let mut pages = [Option <[u8; 8192]>; 128];
但它无法编译。
这编译:
type MyPage = Option<[u8; 8192]>;
let myarray: [MyPage; 128] = [None; 128];
但我不清楚它是否会以正确的格式存储数据,或者如何适当地转换它:
let pages: *mut *mut ::std::os::raw::c_char = myarray.as_mut_ptr() as // what goes here?;
我相信您正在寻找的 Rust 类型是 &[Option<&[u8; 8192]>]
。
C 版本使用双指针,所以你需要确保内部类型是一个引用。 Option<&T>
表明引用可以为空,并且 null pointer optimization 保证它与 T
.
我已经测试过下面的代码可以正常工作, 但我不是 100% 确定这种类型转换是合理的 所以我会在生产代码中小心使用它。
生锈 main.rs
#[link(name = "mylib")]
extern "C" {
pub fn write_stuff(pages: *mut *mut ::std::os::raw::c_char, page_count: u32);
}
pub fn write_stuff_rust(pages: &[Option<&[u8; 8192]>]) {
unsafe { write_stuff(pages.as_ptr() as *mut _, pages.len() as u32) }
}
fn main() {
let page1: [u8; 8192] = [b'a'; 8192];
let page3: [u8; 8192] = [b'b'; 8192];
let page4: [u8; 8192] = [b'c'; 8192];
let page7: [u8; 8192] = [b'd'; 8192];
let pages: Vec<Option<&[u8; 8192]>> = vec![
Some(&page1),
None,
Some(&page3),
Some(&page4),
None,
None,
Some(&page7),
];
write_stuff_rust(&pages);
}
C mylib.c
#include <stdio.h>
#include <stdint.h>
void write_stuff(char **pages, uint32_t page_count) {
for (uint32_t i = 0; i < page_count; i++) {
printf("%d=%p\n", i, pages[i]);
if (pages[i]) {
for (size_t j = 0; j < 8192; j++) {
putchar(pages[i][j]);
}
putchar('\n');
} else {
puts("<empty>");
}
}
}