将 Rust 与 C API 和 mut/pointer 类型问题结合使用
Using Rust with C API and mut/pointer problems with types
我正在尝试使用 Rust 与低级 C API 交互。它需要调用以获取数组的大小,然后使用分配的结构数组再次调用以匹配该大小,函数看起来像
getVals(pNumItems: *mut usize,
pItems: *mut)
根据 API 用法,我这样做:
let mut numItems: usize = 0;
getVals(&numItems,
ptr::null_mut());
// Now we know count, so make an array of MyInfo structs and call again:
let itemInfo: Vec<MyInfo> = Vec::with_capacity(numItems);
getVals(&numItems, itemInfo.as_mut_ptr());
但是第一次调用无法编译,因为我收到错误消息:
mismatched types expected raw pointer *mut u32
found reference &usize
let mut items
我不清楚这里有什么区别。我尝试将其转换为 *mut u32 但抱怨它不安全。这整段代码都是在里面完成的
unsafe{}
所以,我想我做的不正确。有更好的方法吗?
我的向量创建和使用没有编译时错误,但我不确定这是否是预期的方式?
你可能想做这样的事情。
#[repr(C)]
struct MyInfo {
a: i32,
b: f32,
}
extern "C" {
fn getVals(
pNumItems: *mut usize,
pItems: *mut MyInfo,
);
}
fn main() {
// first detect required size
let mut num_items: usize = 0;
unsafe { getVals(&mut num_items, std::ptr::null_mut()) };
// then allocate storage and get items
let mut item_info: Vec<MyInfo> = Vec::with_capacity(num_items);
unsafe { getVals(&mut num_items, item_info.as_mut_ptr()) };
unsafe { item_info.set_len(num_items) };
}
#[repr(C)]
注释确保结构的布局与 C 兼容。
你的函数必须声明为extern "C"
:它的定义不是由 Rust 提供的,并且没有对符号名称应用任何修饰。
调用这样的 extern 函数时,需要一个 unsafe
块(因为 Rust 编译器无法保证此调用的安全性)。
为了获得指向 num_items
的 *mut
指针,您需要从 &mut
引用开始(而不是 &
,后者只能提供 *const
指针)。
调用将数据存储到分配的缓冲区后,您需要调整向量的长度,因为它不知道您对其分配的存储空间做了什么(当然这是不安全的;您是唯一的)知道这是正确的)。
如果编译器抱怨 *mut u32
与 &usize
,那可能是因为您在 getVals()
中声明了 pNumItems: *mut u32
。
如果你真的想要这个(因为在 C 端 uint32_t
是预期的),那么你需要在调用站点声明 let mut num_items: u32 = 0;
并使用 Vec::with_capacity(num_items as usize)
和 .set_len(num_items as usize)
.
我正在尝试使用 Rust 与低级 C API 交互。它需要调用以获取数组的大小,然后使用分配的结构数组再次调用以匹配该大小,函数看起来像
getVals(pNumItems: *mut usize,
pItems: *mut)
根据 API 用法,我这样做:
let mut numItems: usize = 0;
getVals(&numItems,
ptr::null_mut());
// Now we know count, so make an array of MyInfo structs and call again:
let itemInfo: Vec<MyInfo> = Vec::with_capacity(numItems);
getVals(&numItems, itemInfo.as_mut_ptr());
但是第一次调用无法编译,因为我收到错误消息:
mismatched types expected raw pointer
*mut u32
found reference&usize
let mut items
我不清楚这里有什么区别。我尝试将其转换为 *mut u32 但抱怨它不安全。这整段代码都是在里面完成的
unsafe{}
所以,我想我做的不正确。有更好的方法吗?
我的向量创建和使用没有编译时错误,但我不确定这是否是预期的方式?
你可能想做这样的事情。
#[repr(C)]
struct MyInfo {
a: i32,
b: f32,
}
extern "C" {
fn getVals(
pNumItems: *mut usize,
pItems: *mut MyInfo,
);
}
fn main() {
// first detect required size
let mut num_items: usize = 0;
unsafe { getVals(&mut num_items, std::ptr::null_mut()) };
// then allocate storage and get items
let mut item_info: Vec<MyInfo> = Vec::with_capacity(num_items);
unsafe { getVals(&mut num_items, item_info.as_mut_ptr()) };
unsafe { item_info.set_len(num_items) };
}
#[repr(C)]
注释确保结构的布局与 C 兼容。
你的函数必须声明为extern "C"
:它的定义不是由 Rust 提供的,并且没有对符号名称应用任何修饰。
调用这样的 extern 函数时,需要一个 unsafe
块(因为 Rust 编译器无法保证此调用的安全性)。
为了获得指向 num_items
的 *mut
指针,您需要从 &mut
引用开始(而不是 &
,后者只能提供 *const
指针)。
调用将数据存储到分配的缓冲区后,您需要调整向量的长度,因为它不知道您对其分配的存储空间做了什么(当然这是不安全的;您是唯一的)知道这是正确的)。
如果编译器抱怨 *mut u32
与 &usize
,那可能是因为您在 getVals()
中声明了 pNumItems: *mut u32
。
如果你真的想要这个(因为在 C 端 uint32_t
是预期的),那么你需要在调用站点声明 let mut num_items: u32 = 0;
并使用 Vec::with_capacity(num_items as usize)
和 .set_len(num_items as usize)
.