捕获 Rust 生成的恐慌作为 C++ 异常

问题描述 投票:0回答:1

我正在测试 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

到目前为止一切顺利。

我正在尝试将这种恐慌捕获到我的 C++ 代码中。我尝试过以下方法:

// 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 库中生成的恐慌?或者,反过来说,有没有办法将 Rust 恐慌转换为 C++ 可捕获的异常?

c++ rust
1个回答
0
投票

C也不例外

Rust 没有 C++ FFI,只有 C FFI。

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

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

异常不应跨越语言界限

Rust 也没有具体说明。让 C++ 异常跨 C 堆栈帧已经是一场赌博。

无论哪种情况,C 堆栈帧都不会生成任何用于处理展开的代码,因此在异常传播期间展开时不会执行清理,从而导致未定义的行为。在实践中,后果可能是从“正常工作”到“泄漏”再到“损坏状态”。

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

那么如何在 C++ 中处理 Rust 恐慌?

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

即从 Rust 到 C++:

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

如果您忘记了,希望RFC 2945能够(通过中止)拯救您正在经历的事情。

从 C++ 到 Rust:

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

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

© www.soinside.com 2019 - 2024. All rights reserved.