Working with c_void in an FFI

前端 未结 1 1753
一向
一向 2020-12-13 07:02

I am struggling with passing a struct through an FFI that accepts void and reading it back on the other end.

The library in question is libtsm, a terminal state mach

相关标签:
1条回答
  • 2020-12-13 07:48

    You can't cast a struct to c_void, but you can cast a reference to the struct to *mut c_void and back using some pointer casts:

    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);
    

    It is also possible to use std::mem::transmute() function to cast between pointers, but it is much more powerful tool than is really needed here and should be avoided when possible.

    Note that you have to be extra careful casting an unsafe pointer back to a reference. If tsm_screen_draw calls its callback in another thread or stores it in a global variable and then another function calls it, then state local variable may well go out of scope when the callback is called, which will crash your program.

    0 讨论(0)
提交回复
热议问题