< 返回版块

metaworm 发表于 2023-03-07 21:22

很多时候为了实现一些特殊功能,绕不开通过FFI调用底层的系统API,将系统接口的错误转成Rust的错误,然而这个转换过程是非常痛苦的,因为大部分系统API都是C写的,和Rust的处理方式不一样

Rust标准库里封装了常用的Error类型std::io::Error

failed-result引入了一个trait LastError,提供了[LastError::last_error](https://docs.rs/failed-result/0.2.1/failed_result/trait.LastError.html#tymethod.last_error "LastError::last_error") 方法来获取std::io::Error::last_os_error函数返回的last error,而且已经为大部分常见的错误类型和对应的错误值实现了这个trait,比如 bool(false), Option(None), u32(0, Windows平台BOOL类型的FALSE值)还有任意指针类型的空指针

当系统API的返回值是错误值(false/0/空指针..)时,last_error返回Err(last_os_error()),对于非错误值,返回Ok(value)

有了failed-result这个库,就能很方便地将一个系统API的错误转换成Result

use failed_result::*;

let res = OpenProcess(PROCESS_ALL_ACCESS, 0, 0).last_error();
assert_eq!(res.unwrap_err().kind(), ErrorKind::InvalidInput);

如果当前函数也返回一个Result,通过?操作符处理起来会更简单

fn get_process_path(pid: u32) -> anyhow::Result<String> {
    unsafe {
        let handle = OpenProcess(PROCESS_ALL_ACCESS, 0, pid).last_error()?;

        let mut buf = [0u16; MAX_PATH];
        let result = GetModuleFileNameExW(handle, core::ptr::null_mut(), buf.as_mut_ptr(), buf.len() as u32).last_error();
        CloseHandle(handle);
        result?;

        Ok(String::from_utf16(&buf)?)
    }
}

此外,针对Windows平台的HRESULT类型和NTSTATUS类型引入了AsHResultNtStatusResult trait,分别用于将HRESULTNTSTATUS转为Result类型


Ext Link: https://docs.rs/failed-result/latest/failed_result/

评论区

写评论

还没有评论

1 共 0 条评论, 1 页