我一直在用Rust编写Redis模块。这是我第一次使用Rust FFI和绑定。如何调用此方法并在Rust中得到一个数据值而不会破坏Redis指针?
extern "C" {
pub static mut RedisModule_GetTimerInfo: ::std::option::Option<
unsafe extern "C" fn(
ctx: *mut RedisModuleCtx,
id: RedisModuleTimerID,
remaining: *mut u64,
data: *mut *mut ::std::os::raw::c_void,
) -> ::std::os::raw::c_int,
>;
}
请参阅RedisModule_GetTimerInfo API Docs了解更多详细信息。
我最终使它开始工作,但是如果我两次用相同的id
调用它,则会引发错误:
let mut ms = 0 as u64;
let val = "";
let ptr = Box::into_raw(Box::new(&mut val)) as *mut *mut c_void;
let ok = unsafe { RedisModule_GetTimerInfo.unwrap()(ctx, id, &mut ms, ptr) };
let mut data: Option<String> = None;
if ok == 0 {
let val = unsafe { Box::from_raw(*ptr as *mut &str) };
// trim nul bytes
data = Some(val.trim_matches(char::from(0)).to_string());
}
这不起作用,因为Box::from_raw
如何拥有原始指针,并且当放置盒子时指针被销毁。
我尝试了无数种方法来使此工作不使用Box::into_raw
和Box::from_raw
,并且在所有情况下,它们要么最终导致Redis崩溃,要么最终成为我不知道如何转换为&str
的指针。
更新:我最初有一个使用RedisModule_StopTimer
的示例,这是一个错误。已更正以使用我询问的方法。
使用添加的links @Shepmaster中的一个,我终于能够弄清楚这一点。我发誓我尝试过这种变化,但没有想到尝试双重拳击...
这是我所做的:
let val = Box::new(Box::new("") as Box<&str>);
let ptr = Box::into_raw(val);
let ok = unsafe { RedisModule_GetTimerInfo.unwrap()(ctx, id, &mut ms, ptr as *mut *mut c_void) };
let mut data: Option<String> = None;
if ok == 0 {
let val = unsafe {**ptr as &str};
data = Some(val.trim_matches(char::from(0)).to_string());
}
感谢您的帮助!