我试图创建FFI绑定libmodbus,写在C. 这里我偶然发现此function如何创建预期OR-ed字节的C函数的FFI绑定?
modbus_set_error_recovery(ctx,
MODBUS_ERROR_RECOVERY_LINK |
MODBUS_ERROR_RECOVERY_PROTOCOL);
第二个参数被定义为
typedef enum
{
MODBUS_ERROR_RECOVERY_NONE = 0,
MODBUS_ERROR_RECOVERY_LINK = (1<<1),
MODBUS_ERROR_RECOVERY_PROTOCOL = (1<<2)
} modbus_error_recovery_mode;
我bindgen
- 生成绑定是这些:
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum modbus_error_recovery_mode {
MODBUS_ERROR_RECOVERY_NONE = 0,
MODBUS_ERROR_RECOVERY_LINK = 2,
MODBUS_ERROR_RECOVERY_PROTOCOL = 4,
}
and
extern "C" {
pub fn modbus_set_error_recovery(ctx: *mut modbus_t,
error_recovery:
modbus_error_recovery_mode)
-> ::std::os::raw::c_int;
}
我的安全界面看起来像这样,到目前为止:
pub fn set_error_recovery(&mut self, error_recovery_mode: ErrorRecoveryMode) -> Result<()> {
unsafe {
match ffi::modbus_set_error_recovery(self.ctx, error_recovery_mode.to_c()) {
-1 => bail!(Error::last_os_error()),
0 => Ok(()),
_ => panic!("libmodbus API incompatible response"),
}
}
}
和
use std::ops::BitOr;
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum ErrorRecoveryMode {
NONE = 0,
Link = 2,
Protocol = 4,
}
impl ErrorRecoveryMode {
pub fn to_c(self) -> ffi::modbus_error_recovery_mode {
match self {
NONE => ffi::modbus_error_recovery_mode::MODBUS_ERROR_RECOVERY_NONE,
Link => ffi::modbus_error_recovery_mode::MODBUS_ERROR_RECOVERY_LINK,
Protocol => ffi::modbus_error_recovery_mode::MODBUS_ERROR_RECOVERY_PROTOCOL,
}
}
}
impl BitOr for ErrorRecoveryMode {
type Output = Self;
fn bitor(self, rhs: ErrorRecoveryMode) -> ErrorRecoveryMode {
self | rhs
}
}
这触发栈溢出,如果我叫set_error_recovery
这样
assert!(modbus.set_error_recovery(ErrorRecoveryMode::Link | ErrorRecoveryMode::Protocol).is_ok())
错误是
thread 'set_error_recovery' has overflowed its stack
fatal runtime error: stack overflow