c++ - 将数组从 C++ 返回到 Rust FFI 中的 rust
问题描述
我有一个用 C++ 编写的函数,它将从 Rust 调用。这个函数构造一个数组并且必须把它返回给 Rust:
main.rs
extern crate libc;
use libc::c_void;
extern {
fn construct_array(arr_ptr: *mut u32, arr_size: u32) -> c_void;
}
fn main() {
let arr_size: usize = 4;
let mut arr: Vec<u32> = Vec::with_capacity(arr_size);
unsafe {
construct_array(arr.as_mut_ptr(), arr_size as u32);
let result = std::slice::from_raw_parts(arr.as_mut_ptr(), arr_size);
println!("Result from rust {:?}", result);
}
}
函数.cpp
extern "C" void construct_array(uint32_t* arr_ptr, uint32_t arr_size) {
uint32_t arr[arr_size];
for (uint32_t i = 0; i < arr_size; i++) {
arr[i] = i;
}
// Print array items
printf("Result from c++ [");
printf("%u", arr[0]);
for (uint32_t i = 1; i < arr_size; i++) {
printf(", %u", arr[i]);
}
printf("]\n");
arr_ptr = &arr[0];
}
但是,当我运行它时,会打印以下内容:
$ cargo run
Result from c++ [0, 1, 2, 3]
Result from rust [0, 0, 0, 0]
如何在 C++ 中正确构造一个数组并通过 FFI 将其传递给 Rust?
解决方案
您的问题可以仅在 C++ 中演示:
int main() {
uint32_t foo[12];
construct_array(foo, 12);
printf("Actual result from C++:");
for (auto i = 0; i < 12; ++i) printf("%u\n", foo[i]);
}
这会打印垃圾,并且来自您“复制”数组的方式:
arr_ptr = &arr[0];
这会将数组的地址分配给局部变量arr_ptr
,并且什么也不做。即使这可行,您也会让本地数组的地址转义,那就是 UB。相反,您可以跳过arr
缓冲区并直接使用传递给您的函数的数组:
extern "C" void construct_array(uint32_t* arr_ptr, uint32_t arr_size) {
for (uint32_t i = 0; i < arr_size; i++) {
arr_ptr[i] = i;
}
// Print array items
printf("Result from c++ [");
printf("%u", arr_ptr[0]);
for (uint32_t i = 1; i < arr_size; i++) {
printf(", %u", i);
}
printf("]\n");
}
推荐阅读
- blazor - 如何使用输入参数动态更改 Blazor Webassembly 中的相同布局
- html - HTML 渲染器 - 字母间距 CSS 不起作用
- symfony - Symfony 多个实体管理器/连接问题
- c - TCP 套接字:recv() 没有收到我的完整数据
- javascript - 对于嵌套数组,如何重新排列顺序,使数组的最后一个字符串项等于下一个字符串的第一个字符串项?
- ruby-on-rails - Ruby on Rails 5.2 - ArgumentError:传递要在 :if 和 :unless 中评估的字符串不支持条件选项
- python - 如何绕过“NoneType”对象没有属性“文本”
- node.js - 在 nodejs10 上运行的 Google Cloud Function 测试失败
- amazon-web-services - 当应用程序在支持无头图形的 Ec2 实例上启动时,IDirect3D9::CheckDeviceType 返回 D3DERR_NOTAVAILABLE
- django - Django-mailer 自定义管理区域