Cam*_*art 5 c++ string interop rust
我正在尝试在Rust中构建Octave函数.Octave的API是用C++编写的,所以我使用了rust-bindgen生成了绑定.我正在解决尝试生成包含的绑定std::string时出现的问题.如果我可以将它指向C++的std::string不透明和有效指针,那将是很好的.我是否可以在需要传递C++时在C++端构建实用程序功能std::string?
当我第一次尝试这个时,我很天真.这显然是错误的.Rust std::ffi:CString用于C字符串,而不是C++字符串.我发现这篇最近的博客在比较两者时很有帮助.我的第一次尝试看起来像这样:
#![allow(non_snake_case)]
#![allow(unused_variables)]
extern crate octh;
// https://thefullsnack.com/en/string-ffi-rust.html
use std::ffi::CString;
#[no_mangle]
pub unsafe extern "C" fn Ghelloworld (shl: *const octh::root::octave::dynamic_library, relative: bool) -> *mut octh::root::octave_dld_function {
let name = CString::new("helloworld").unwrap();
let pname = name.as_ptr() as *const octh::root::std::string;
std::mem::forget(pname);
let doc = CString::new("Hello World Help String").unwrap();
let pdoc = doc.as_ptr() as *const octh::root::std::string;
std::mem::forget(pdoc);
octh::root::octave_dld_function_create(Some(Fhelloworld), shl, pname, pdoc)
}
pub unsafe extern "C" fn Fhelloworld (args: *const octh::root::octave_value_list, nargout: ::std::os::raw::c_int) -> octh::root::octave_value_list {
let list_ptr = ::std::ptr::null_mut();
octh::root::octave_value_list_new(list_ptr);
::std::ptr::read(list_ptr)
}
Run Code Online (Sandbox Code Playgroud)
我需要将函数名称和文档作为字符串传递给octave_dld_function_create.我希望有一个CppString我可以使用的.有关如何进行的任何建议?
这是一个经典的FFI问题,解决方案是使用“沙漏”设计:语言A <=>通用ABI <=>语言B。
当然,有可能发展bindgen,以便它可以忠实地再现C ++ ABI,但实际上,它需要一个完整的C ++编译器,这可能会花费很多精力。
使用“沙漏”设计,ABI困难的每种语言都使用自己的专用工具链来转换为特定的知名ABI。在这种情况下,它将是C ++ <=> C <=> Rust。
一种可能的解决方案是围绕C ++ API创建一个C包装器库,然后在其上使用bindgen。这就是LLVM和Clang项目所做的。
这是最简单的解决方案,Octavo项目可能非常愿意在树中集成这样的octavo-c立面(始终最好地确保它是最新的)。
另一个解决方案是为bindgen创建一个C ++随行库,该库负责为常见的C ++类型(例如std::string)提供C-ABI 。这将是一个更加困难的工作,尤其是因为: