Rust FFI que pasa el objeto de rasgo como contexto para llamar a las devoluciones de llamada

Bien, estoy tratando de lograr lo siguiente:

C llama a la oxidaciónrust vuelve a llamar a c y registra una devolución de llamada en un objeto de rasgo definido por el usuarioc invoca óxido con el contextoRust llama a la devolución de llamada en el contexto (objeto de rasgo)

He estado jugando un poco con eso. Llegué bastante lejos, pero todavía no del todo.

El bit C:

#include <dlfcn.h>
#include <stdio.h>

void *global_ctx;

void c_function(void* ctx) {
    printf("Called c_function\n");
    global_ctx = ctx;
}

int main(void) {
    void *thing = dlopen("thing/target/debug/libthing.dylib", RTLD_NOW | RTLD_GLOBAL);
    if (!thing) {
        printf("error: %s\n", dlerror());
        return 1;
    }
    void (*rust_function)(void) = dlsym(thing, "rust_function");
    void (*rust_cb)(void*) = dlsym(thing, "rust_cb");
    printf("rust_function = %p\n", rust_function);
    rust_function();

    rust_cb(global_ctx);
}

El bit de óxido:

extern crate libc;


pub trait Foo {
    fn callback(&self);
}

extern {
    fn c_function(context: *mut libc::c_void);
}

pub struct MyFoo;
impl Foo for MyFoo {
    fn callback(&self) {
        println!("callback on trait");
    }
}

#[no_mangle]
pub extern fn rust_cb(context: *mut Foo) {
    unsafe {
        let cb:Box<Foo> = Box::from_raw(context);
        cb.callback();
    }
}

#[no_mangle]
pub extern fn rust_function() {
    println!("Called rust_function");
    let tmp = Box::new(MyFoo);
    unsafe {
        c_function(Box::into_raw(tmp) as *const Foo as *mut libc::c_void);
    }
}

La cuestión:

Mi programa falla cuando intento llamar a "devolución de llamada" en el objeto de rasgo en "rust_cb"

Una solución: - Cambie la firma de la función de "rust_cb" a

pub extern fn rust_cb(context: *mut MyFoo)

pero eso no es lo que quiero, ya que estoy tratando de crear un contenedor seguro que solo conozca el rasgo del oyente

Cualquier ayuda apreciada

PD: mi suposición es que se produce una falla, porque el compilador no conoce el desplazamiento de la devolución de llamada en el rasgo Foo, necesita el objeto real para determinar dónde está. pero entonces no tengo idea de cómo solucionar eso

Respuestas a la pregunta(2)

Su respuesta a la pregunta