gpt4 book ai didi

rust - 通过 FFI 获取和设置最后一条错误消息的正确方法是什么?

转载 作者:行者123 更新时间:2023-11-29 08:02:48 25 4
gpt4 key购买 nike

我正在包装一个 C API (dylib),为最后一条错误消息公开一个 setter 和 getter API:

extern "C" {
/// GetLastError is thread-safe
pub fn GetLastError() -> *const ::std::os::raw::c_char;
pub fn SetLastError(msg: *const ::std::os::raw::c_char);
}

最简单的包装方式如下

use std::error::Error;
use std::ffi::CStr;
use std::fmt::{self, Display, Formatter};
use std::os::raw::c_char;

pub struct MyError;

impl MyError {
pub fn get_last() -> &'static str {
unsafe {
match CStr::from_ptr(c_api::GetLastError()).to_str() {
Ok(s) => s,
Err(_) => "Invalid UTF-8 message",
}
}
}

pub fn set_last(msg: &'static str) {
unsafe {
c_api::SetLastError(msg.as_ptr() as *const c_char);
}
}
}

impl Display for MyError {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}", MyError::get_last())
}
}

impl Error for MyError {
fn description(&self) -> &'static str {
MyError::get_last()
}

fn cause(&self) -> Option<&Error> {
None
}
}

这似乎可以正常获取最后一条错误消息。然而,设置最后一条错误消息似乎很天真,它会把堆栈框架中以前的消息弄乱!

例如;

let msg: &'static str = "invalid";
MyError::set_last(msg);
println!("Last error msg: {}", MyError::get_last());

输出上次错误信息:invalidLast error msg,或者

assert_eq!(MyError::get_last().trim(), msg);

失败

thread 'tests::set_error' panicked at 'assertion failed: `(left == right)`
left: `"invalidassertion failed: `(left == right)`\n left: ``,\n right: ``"`,
right: `"invalid"`'

这样做的正确方法是什么?

我想到了使用 backtrace ,但在 crate 中找不到什么解释,而且无处可寻!

最佳答案

Rust 字符串不是以 0 结尾的,但是,当您这样做时,您假设它们是:

c_api::SetLastError(msg.as_ptr() as *const c_char);

因为 C API 通过空字节的存在来检测字符串的结尾。

正确的做法是:

let c_string = CString::new("message").unwrap(); // will add a null byte
unsafe {
c_api::SetLastError(c_string.as_ptr());
}

根据 C API 是否复制字符串,您可能需要使用 into_raw 并在必要时进行适当的反初始化处理。

关于rust - 通过 FFI 获取和设置最后一条错误消息的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51921872/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com