与C++ std :: string的Rust interop

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我可以使用的.有关如何进行的任何建议?

Mat*_* M. 5

这是一个经典的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 。这将是一个更加困难的工作,尤其是因为:

  • C没有泛型,因此C ++模板必须不在范围内,或者预先实例化的模板必须一次包装一个,
  • C不知道如何调用移动或复制构造函数,因此,除非C ++类型已经是POD,否则必须通过不透明的指针进行操作,
  • C不知道...