c++ - Rust 与 C++ std::string 互操作

标签 c++ string rust interop

我正在尝试用 Rust 构建 Octave 函数。 Octave 的 API 使用 C++,因此我使用 rust-bindgen 生成了绑定(bind)。我目前正在解决尝试生成 bindings that include std::string 时出现的问题.如果我可以将它保留为不透明且有效的指向 C++ std::string 的指针,那就太好了.是否可以在我需要传入 C++ std::string 时在 C++ 端构建实用函数?

当我第一次尝试这个时,我很天真。这显然是错误的。使用rust std::ffi:CString适用于 C 字符串,而不是 C++ 字符串。我找到了 this recent blog比较两者时很有帮助。我的第一次尝试看起来是like this :

#![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)
}

我需要将函数名称和文档作为字符串传递给 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 facade(这总是最好保证它是最新的)。


另一种解决方案是为 bindgen 创建一个 C++ 配套库,它负责为常见的 C++ 类型(例如 std::string)提供 C-ABI。这将是一项更困难的工作,尤其是因为:

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

关于c++ - Rust 与 C++ std::string 互操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46524781/

相关文章:

java - 从 Java 字符串中获取数据

java - JUnit 测试用例不工作

rust - 当我无法实现 Ord 时如何使用 BinaryHeap?

rust - 如何在结构上存储回调列表?

c++ - 反作弊客户端

c++ - 我如何为此二进制搜索函数创建具有修改后的最大/最小值的新数组

java - 如何根据多个分隔符 split() 字符串?

functional-programming - 在 map 内部使用 if 时如何处理 "if may be missing an else clause"?

c++ - 不要声明 C 风格的数组,而是使用 std::array<>

c++ - 使用 openGL 缩放和移动 3d 对象