Rust 如何将结果映射为数字错误代码?

Rust 如何将结果映射为数字错误代码?,rust,Rust,我使用C调用了一系列FFI函数。调用方希望成功时为1,失败时为-1 结构错误; fn我的生锈函数->结果{ 好啊 } [allownon_snake_案件] pub extern C fn从\u C->i32调用\u{ 让结果=我的函数; 比赛结果{ 好的=>1, 错误=>-1, } } 有没有更惯用的方法将我的结果转换为1/-1返回代码?您可以使用它创建一个类型,在该类型中可以实现并且仍然表示i32,这允许编译检查您是否正确地转换了结果,前提是您的from实现中没有bug,因此可能需要添加一些

我使用C调用了一系列FFI函数。调用方希望成功时为1,失败时为-1

结构错误; fn我的生锈函数->结果{ 好啊 } [allownon_snake_案件] pub extern C fn从\u C->i32调用\u{ 让结果=我的函数; 比赛结果{ 好的=>1, 错误=>-1, } } 有没有更惯用的方法将我的结果转换为1/-1返回代码?

您可以使用它创建一个类型,在该类型中可以实现并且仍然表示i32,这允许编译检查您是否正确地转换了结果,前提是您的from实现中没有bug,因此可能需要添加一些单元测试

类型MyResult=Result; fn my\u rust\u函数->MyResult{ 好啊 } [报告透明] 发布结构结果{ 代码:i32, //代码:libc::c_int,//如果您的c库期望的是'c_int',而不是'i32` } 从中为CResult执行impl{ fn fromresult:MyResult->Self{ 让代码=匹配结果{ 好的=>1, 错误=>-1, }; 自我{代码} } } [allownon_snake_案件] pub extern C fn从\u C->CResult调用\u{ 让结果=我的函数; 结果 } 您还可以将枚举用于:

[现场][32] pub enum CResult{ NoError=1, 错误=-1, } 从中为CResult执行impl{ fn fromresult:MyResult->Self{ 比赛结果{ 好的=>CResult::NoError, Err_uz=>CResult::Error, } } } 在夜间,您还可以实施:

![特征特征] 使用std::ops::Try; 类型MyResult=Result; fn my\u rust\u函数->MyResult{ 好啊 } [现场][32] pub enum CResult{ NoError=1, 错误=-1, } 从中为CResult执行impl{ fn fromresult:MyResult->Self{ 比赛结果{ 好的=>CResult::NoError, Err_uz=>CResult::Error, } } } 从中为MyResult执行impl{ fn fromcresult:CResult->Self{ 比赛成绩{ CResult::NoError=>Ok, CResult::Error=>Err, } } } 求结果{ 类型Ok=; 类型错误=; fn进入_resultself->MyResult{ 自我陶醉 } fn from_ok_:::ok->Self{ 无错误 } fn来自_错误:::错误->自我{ Self::错误 } } [allownon_snake_案件] pub extern C fn从\u C->CResult调用\u{ 让u=我的函数?; CResult::NoError } 注意:使用枚举方法时要小心,确保您的实现是兼容的。[reprlibc::c_int]是我们真正想要的,但我不知道用什么方式来表达这一点。因此,如果库需要c_int,那么具有reprttransparent的结构可能更安全。

我会创建一个扩展特性:

另见:


这就是我要做的——很清楚正在执行的是什么。您可以执行result.map | | | 1.map | err | | |-1.unwrap,但这样会创建不必要的闭包。为什么需要[ReprtTransparent]呢?这不会影响您编写代码的方式,而且我相当肯定编译器会以任何方式进行优化。@jhpratt,因为如果没有详细的答案,这将是UB。我没有想过创建枚举,但这是一个非常简洁的解决方案。我将@shepmaster response标记为答案,因为它在精神上最接近于我试图实现的目标。
trait FfiError {
    fn as_c_error(&self) -> i32;
}

impl<T, E> FfiError for Result<T, E> {
    fn as_c_error(&self) -> i32 {
        match self {
            Ok(_) => 1,
            Err(_) => -1,
        }
    }
}
pub extern "C" fn called_from_c() -> i32 {
    my_rust_function().as_c_error()
}