我有以下从 C 代码调用的线程过程的代码。
context
是指向堆 (Box::into_raw(Box::new(...))
上的结构的指针。闭包被传递给 add_callback
函数并存储在回调向量中,以便稍后从另一个函数调用。如何修改闭包内app_context
的字段?
#[no_mangle]
pub unsafe extern "C" fn worker_thread_proc(context: *mut c_void) -> c_int {
unsafe {
let app_context = context as *mut AppContext;
let my_closure = Rc::new(|a: N, _, _, _| {
(*app_context).foo = 0; // HOW TO DO THIS PROPERLY?
0
});
// save the closure to a Vec in an object
...
}
}
尝试直接编码会导致可以理解的错误,因为
app_context
被闭包借用了。
error[E0597]: `app_context` does not live long enough
...
}
- `app_context` dropped here while still borrowed
但是我知道,即使在
worker_thread_proc
函数完成之后,原始指针指向的对象仍将继续有效。在这种情况下,我怎样才能实现修改上下文结构状态的预期目标?
我尝试在指针上使用
Rc
并在使用前克隆它,但这也会产生 does not live long enough
错误。我相信也应该有一些方法可以通过Box
来做到这一点,但我自己无法弄清楚。
假设这是 MRE:
use core::ffi::c_void;
struct AppContext {
foo: usize,
}
#[no_mangle]
pub unsafe extern "C" fn worker_thread_proc(context: *mut c_void) {
let closure;
unsafe {
let app_context = context as *mut AppContext;
let my_closure = Box::new(|| {
(*app_context).foo = 0; // HOW TO DO THIS PROPERLY?
0
});
closure = my_closure;
}
println!("{:p}", &closure);
}
问题在于,要取消引用指针,您所需要的只是对它的引用,但这意味着闭包可以(因此将)通过引用获取
app_context
,然后导致编译器出错
error[E0597]: `app_context` does not live long enough
--> src/lib.rs:13:13
|
12 | let my_closure = Box::new(|| {
| -- value captured here
13 | (*app_context).foo = 0; // HOW TO DO THIS PROPERLY?
| ^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
...
17 | }
| - `app_context` dropped here while still borrowed
18 |
19 | println!("{:p}", &closure);
| -------- borrow later used here
要解决这个问题,您可以使用
app_context
关键字强制编译器复制指针 move
:
let my_closure = Box::new(move || { /*…*/ });