我如何将* mut * mut c_void转换为不带Box :: from_raw的&str?

问题描述 投票:0回答:1

我一直在用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_rawBox::from_raw,并且在所有情况下,它们要么最终导致Redis崩溃,要么最终成为我不知道如何转换为&str的指针。

更新:我最初有一个使用RedisModule_StopTimer的示例,这是一个错误。已更正以使用我询问的方法。

rust ffi
1个回答
0
投票

使用添加的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());
    }

感谢您的帮助!

© www.soinside.com 2019 - 2024. All rights reserved.