Rust 如何将*mut*mut c_void转换为&;str不带Box::从_raw开始?
我一直在用Rust编写Redis模块。这是我第一次尝试使用Rust FFI和绑定。我如何调用此方法,并在不破坏Redis指针的情况下以Rust中的数据值结束Rust 如何将*mut*mut c_void转换为&;str不带Box::从_raw开始?,rust,ffi,Rust,Ffi,我一直在用Rust编写Redis模块。这是我第一次尝试使用Rust FFI和绑定。我如何调用此方法,并在不破坏Redis指针的情况下以Rust中的数据值结束 extern "C" { pub static mut RedisModule_GetTimerInfo: ::std::option::Option< unsafe extern "C" fn( ctx: *mut RedisModuleCtx, id: Red
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,
>;
}
这不起作用,因为Box::from_raw
是如何拥有原始指针的,并且在删除该框时指针会被销毁
我尝试了无数种方法,在不使用Box::into_raw
和Box::from_raw
的情况下实现了这一点,所有时候,它们要么崩溃了Redis,要么变成了我不知道如何转换为&str
的指针
更新:我最初有一个使用RedisModule\u StopTimer
的例子,这是一个错误。更正为使用我询问的方法。使用添加的@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());
}
让val=Box::new(Box::new(“”)作为Box);
让ptr=Box::输入原始值(val);
让ok=unsafe{RedisModule_GetTimerInfo.unwrap()(ctx,id,&mut-ms,ptr-as*mut*mut-c_-void)};
让mut数据:选项=无;
如果ok==0{
设val=unsafe{**ptr as&str};
data=Some(val.trim_匹配(char::from(0)).to_string());
}
谢谢大家的帮助 使用@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());
}
让val=Box::new(Box::new(“”)作为Box);
让ptr=Box::输入原始值(val);
让ok=unsafe{RedisModule_GetTimerInfo.unwrap()(ctx,id,&mut-ms,ptr-as*mut*mut-c_-void)};
让mut数据:选项=无;
如果ok==0{
设val=unsafe{**ptr as&str};
data=Some(val.trim_匹配(char::from(0)).to_string());
}
谢谢大家的帮助 我是板条箱的维护者之一,板条箱为编写Redis模块提供了一个高级的Rust API 在您的问题的提示下,我考虑以安全的方式将这些计时器API添加到板条箱中,并将在完成后将代码推送到repo 以下代码显示了如何安全地检索数据:
// Create local variables to hold the returned values
let mut remaining: u64 = 0;
let mut data: *mut c_void = std::ptr::null_mut();
// Call the API and retrieve the values into the local variables
let status = unsafe {
RedisModule_GetTimerInfo.unwrap()(ctx, timer_id, &mut remaining, &mut data)
};
if status == REDISMODULE_OK {
// Cast the *mut c_void supplied by the Redis API to
// a raw pointer of our custom type:
let data = data as *mut T; // T is the type of the data, e.g. String
// Dereference the raw pointer (we know this is safe,
// since Redis should return our original pointer which
// we know to be good), and turn in into a safe reference:
let data = unsafe { &*data };
println!("Remaining: {}, data: {:?}", remaining, data);
}
我是板条箱的维护人员之一,板条箱为编写Redis模块提供了高级Rust API 在您的问题的提示下,我考虑以安全的方式将这些计时器API添加到板条箱中,并将在完成后将代码推送到repo 以下代码显示了如何安全地检索数据:
// Create local variables to hold the returned values
let mut remaining: u64 = 0;
let mut data: *mut c_void = std::ptr::null_mut();
// Call the API and retrieve the values into the local variables
let status = unsafe {
RedisModule_GetTimerInfo.unwrap()(ctx, timer_id, &mut remaining, &mut data)
};
if status == REDISMODULE_OK {
// Cast the *mut c_void supplied by the Redis API to
// a raw pointer of our custom type:
let data = data as *mut T; // T is the type of the data, e.g. String
// Dereference the raw pointer (we know this is safe,
// since Redis should return our original pointer which
// we know to be good), and turn in into a safe reference:
let data = unsafe { &*data };
println!("Remaining: {}, data: {:?}", remaining, data);
}
&str
是一个胖指针,它永远不能放在*mut c_void
中。您需要添加更多间接寻址,如。同样相关的是,我想知道你是如何得到数据的:*mut*mut::std::os::raw::c_void,
在c中。它看起来像是坏的c代码。不清楚你是如何使用这个API的。通过浏览文档,您似乎需要将原始指针传递到RedisModule\u CreateTimer
,当您使用非空数据指针调用RedisModule\u CreateTimerInfo
时,它会将原始指针复制到指针对象中。所以您使用什么值创建计时器?你链接到的函数和问题中的代码示例之间有什么联系?(你是无意中链接错了吗?@trentcl抱歉,是的。你说得对。我已经纠正了这个例子。RedisModule\u StopTimer
使用*mut*mut c\u void
读取数据进行类似的操作。&str
是一个胖指针,它永远无法放入*mut c\u void
中。您需要添加更多间接寻址,如。同样相关的是,我想知道你是如何得到数据的:*mut*mut::std::os::raw::c_void,
在c中。它看起来像是坏的c代码。不清楚你是如何使用这个API的。通过浏览文档,您似乎需要将原始指针传递到RedisModule\u CreateTimer
,当您使用非空数据指针调用RedisModule\u CreateTimerInfo
时,它会将原始指针复制到指针对象中。所以您使用什么值创建计时器?你链接到的函数和问题中的代码示例之间有什么联系?(你是无意中链接错了吗?@trentcl抱歉,是的。你说得对。我已经纠正了这个例子。RedisModule\u StopTimer
使用*mut*mut c\u void
读取数据来执行类似的操作。Box::from_raw
+Box::leak
当您已经有了*mut字符串时,似乎有点迂回;有没有理由不简单地取消引用<代码>让数据:&String=&*(数据为*mut_389;)代码>这是一个很好的观点。我相信这样写可以让代码的读者清楚地看到,数据源于框
。我还猜想编译后的代码会非常相似。接下来,我又考虑了一些,并考虑将我的代码改为使用常规引用,而不是Box
es,这只是一个特例。我来看看它是如何工作的。我突然意识到,与框::from_raw
相比,取消引用还有一个优势,即您可以从同一个*mut String
创建多个共享引用,而框的别名是不合理的,因此,当任何数据仍然挂起时,您必须小心不要再次调用Box::from_raw
。(当然,这只适用于您不需要&mut
访问字符串的情况)是的,这确实是一个显著的优势。Box::from_raw
+Box::leak
在您已经拥有*mut字符串的情况下似乎有点迂回;有没有理由不简单地取消引用<代码>让数据:&String=&*(数据为*mut_389;)代码>这是一个很好的观点。我相信是这样写的