如何通过原始指针修改闭包内的结构体字段?

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

我有以下从 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
来做到这一点,但我自己无法弄清楚。

rust unsafe
1个回答
0
投票

假设这是 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 || { /*…*/ });
© www.soinside.com 2019 - 2024. All rights reserved.