Okay, I'm trying to achieve the following:
- C calls into rust
- rust calls back into c and registers a callback on a user defined trait object
- c calls into rust with the context
- rust calls the callback on the context (trait object)
I've been playing around with it quite a bit. I got quite far, but still not quite there.
The C bit:
#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);
}
The rust bit:
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);
    }
}
The issue:
- My program segfaults when I try to call "callback" on the trait object in "rust_cb"
One Solution: - Change the function signature of "rust_cb" to
pub extern fn rust_cb(context: *mut MyFoo)
but that's not what I want, as I'm trying to create a safe wrapper that only knows the trait of the listener
Any help appreciated
PS: my assumption is that it segfaults, because the compiler doesn't know the offset of callback on the trait Foo, it needs the actual object to determine where it is. but then i have no idea how to work around that
 
    