gpt4 book ai didi

ffi - 在 FFI 中使用 c_void

转载 作者:行者123 更新时间:2023-11-29 07:41:48 26 4
gpt4 key购买 nike

我正在努力通过接受 void 的 FFI 传递结构并在另一端读回它。

有问题的库是 libtsm,一个终端状态机。它允许您提供输入,然后找出输入后终端将处于哪种状态。

它将其绘制函数声明为:

pub fn tsm_screen_draw(con: *tsm_screen, draw_cb: tsm_screen_draw_cb, data: *mut c_void) -> tsm_age_t;

其中 tsm_screen_draw_cb 是由库用户实现的回调,带有签名:

pub type tsm_screen_draw_cb = extern "C" fn(
con: *tsm_screen,
id: u32,
ch: *const uint32_t,
len: size_t,
width: uint,
posx: uint,
posy: uint,
attr: *tsm_screen_attr,
age: tsm_age_t,
data: *mut c_void
);

这里重要的部分是data参数。它允许用户通过一个指向自实现状态的指针,对其进行操作并在绘制后使用它。给定一个简单的结构:

struct State {
state: int
}

我该如何正确地做到这一点?我不确定如何正确地将指向结构的指针转换为 void 并返回。

最佳答案

您不能将struct 转换为c_void,但可以将reference 转换为*mut c_void 并返回使用一些指针转换:

fn my_callback(con: *tsm_screen, ..., data: *mut c_void) {
// unsafe is needed because we dereference a raw pointer here
let data: &mut State = unsafe { &mut *(data as *mut State) };
println!("state: {}", data.state);
state.x = 10;
}

// ...

let mut state = State { state: 20 };
let state_ptr: *mut c_void = &mut state as *mut _ as *mut c_void;
tsm_screen_draw(con, my_callback, state_ptr);

也可以使用 std::mem::transmute() 函数在指针之间进行转换,但它比这里真正需要的工具强大得多,应尽可能避免使用。

请注意,您必须格外小心地将不安全指针强制转换回引用。如果 tsm_screen_draw 在另一个线程中调用它的回调或将其存储在全局变量中,然后另一个函数调用它,那么当回调执行时,state 局部变量很可能超出范围调用,这将使您的程序崩溃。

关于ffi - 在 FFI 中使用 c_void,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24191249/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com