【发布时间】:2022-10-09 11:33:34
【问题描述】:
我正在尝试将一个小的 rust 库嵌入到我的 C++ 代码库中,我使用 cargo-c(我认为它使用 cbindgen ?)来创建一些简单的 rust C api,rust side api,如下所示:
#[no_mangle]
pub extern "C" write_result_to_cpp_callback(
cpp_callback : Option<extern "C" fn( i64 )>)
(它基于回调而不是返回值,因为 rust 部分实际上运行一个 tokio 运行时来执行 io 作业,并且对 rust 的任何调用都是非阻塞的)
现在我需要传递一些复杂的结构而不是简单的 i64,似乎 cxx.rs 使这更简单,但是 cxx.rs 函数指针部分文档说
Passing a function pointer from C++ to Rust is not implemented yet, only from Rust to an extern "C++" function is implemented.
我想知道我是否可以在我的 cbindgen C API 中使用 cxx.rs 生成的类型?例如
// for cxx.rs
#[cxx::bridge]
mod ffi{
struct MyStruct{
my_vec: Vec<String>
}
}
// for cbindgen
#[no_mangle]
pub extern "C" write_result_to_cpp_callback(
cpp_callback : Option<extern "C" fn( *const ffi::MyStruct )>)
如果这样的用法没问题,cbindgen 导出的 api 是否也会对某些容器使用与 cxx.rs 相同的 API,例如下面的代码也可以工作?
// will this Vec have compatible memory layout as I use
// the cxx.rs generated C++ code ?
#[no_mangle]
pub extern "C" write_result_to_cpp_callback(
cpp_callback : Option<extern "C" fn( *const Vec<ffi::MyStruct> )>)
// or I need to also wrap the Vec as a cxx.rs struct member
// just like following ?
mod ffi{
struct WrapVec{
my_vec: Vec<MyStruct>
}
}
#[no_mangle]
pub extern "C" write_result_to_cpp_callback(
cpp_callback : Option<extern "C" fn( *const WrapVec)>)
感谢您的建议
【问题讨论】:
-
你看过 cxx.rs/async.html 和 cxx.rs/binding/vec.html 吗?
-
感谢您提供的信息,但是示例和我的用法之间仍然存在差距,IIUC,异步显示在 cxx.rs 中声明的 C++ fn 应该识别 cxx.rs 内置类型,包括 Vec<T>,但是如果从 rust 调用它,我是直接通过 ffi 调用(因此内存布局兼容),还是调用 cxx.rs wrap fn? , 并且 vec 显示 rust 函数可以调用 C++ 并传递 rust::Vec<T>,IIRC rust 需要标记 struct repr(C) 以使其与 C 兼容,但我没有在 rust 中找到 Vec 的 wrap 类型,那么这是否意味着 rust std 默认中的 Vec 标记为 repr(C)?
-
据我了解,
rust::Vec<T>持有一个指向 Rust Vec 的指针,每个函数调用都调用 Rust 以在 Vec 上执行该操作。就像,rust_vec.push_back(val)将该值传递给 Rust,然后从 Rust 端调用vec.push(val)。