我正在测试Rust库,这些库可能会崩溃,并在C++代码中使用它们.我有以下图书馆:

Cargo.toml:

[package]
name = "boom"
version = "0.1.0"
edition = "2018"

[dependencies]
libc = "0.2"

[lib]
crate-type=["staticlib"]

src/lib.rs:

#[no_mangle]
pub extern "C" fn boom() {
    panic!("Oh no, something went wrong!");    
}

我正在使用cargo build构建它,并使用以下C++代码(boom.cpp文件)中的结果:

// g++ -g boom.cpp -L./target/debug -lboom -o boom

extern "C" {
    void boom();
}

int main() {
    boom();
}

结果是:

thread '<unnamed>' panicked at src/lib.rs:3:5:
Oh no, something went wrong!
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
fatal runtime error: failed to initiate panic, error 5

到目前为止一切顺利.

我试图将这种panic 捕捉到我的C++代码中.我try 了以下操作:

// g++ -g boom.cpp -L./target/debug -lboom -o boom

#include <stdexcept>

extern "C" {
    void boom();
}

int main() {
    try
    {
      boom();
    }
    catch(const std::exception& e)
    {
      printf("exception captured\n");
    }
}

但结果是相同的,而不是预期的exception captured消息.

C++代码中是否有任何方法可以捕捉Rust库产生的panic ?或者,反过来说,有没有办法将Rustpanic 转化为C++可捕获的异常?

推荐答案

C也不例外

Rust没有C++ FFI,但只有C FFI.

C中没有异常,因此没有指定用于异常传播的ABI.

因此,没有标准机制将异常从Rust传播到C(或从C传播到Rust),这不会有太大帮助,因为无论如何都没有办法与C中的异常交互.

收件箱不应跨越语言界限

Rust这里也没有具体内容.让C++异常跨C堆栈框架已经是一场赌博.

在任何一种情况下,C栈帧都不会生成任何用于处理展开的代码,因此在异常传播期间展开时不会执行清理,结果为Undefined Behavior.在实践中,后果从"公正有效"到"泄密"到"腐败状态"不等.

除非工具链保证显式兼容性,否则异常不应跨越语言界限.

那么如何在C++中处理Rustpanic 呢?

通过在FFI边界手动或自动翻译它们.

也就是说,从Rust到C++:

  1. 在Rust端,使用catch_unwind将异常转换为错误.
  2. 在C++端,处理错误(可能再次抛出).

如果您忘记了,希望RFC 2945能像您所经历的那样拯救您(通过中止).

从C++到Rust:

  1. 在C++端,使用catch将异常转换为错误.
  2. 在Rust方面,处理错误(可能再次panic ).

如果您忘记了,您就正式进入了未定义行为的领域.祝你好运

Rust相关问答推荐

为什么函数不接受选项T参数的所有权?

是否可以为`T:Copy`执行`T. clone`的测试

为什么类型需要在这个代码中手动指定,在rust?

通过使用光标拖动角来绕其中心旋转矩形

无法理解铁 rust &S错误处理

如何在递归数据 struct 中移动所有权时变异引用?

一种随机局部搜索算法的基准(分数)

Rust 的多态现象.AsRef与Derf

对reqwest提供的这种嵌套JSON struct 进行反序列化

为什么 tokio 在以奇怪的方式调用时只运行 n 个任务中的 n-1 个?

如何在 `connect_activate()` 之外创建一个 `glib::MainContext::channel()` 并将其传入?

`use` 和 `crate` 关键字在 Rust 项目中效果不佳

当推送到 HashMap 中的 Vector 时,类型 `()` 无法取消引用

如何将 &[T] 或 Vec<T> 转换为 Arc<Mutex<[T]>>?

无法将`&Vec>`转换为`&[&str]`

是否可以通过可变引用推进可变切片?

std::vector::shrink_to_fit 如何在 Rust 中工作?

如何递归传递闭包作为参数?

如何存储返回 Future 的闭包列表并在 Rust 中的线程之间共享它?

为什么我可以从读取的可变自引用中移出?