Rust FFI передает объект черты в качестве контекста для вызова обратных вызовов на
Хорошо, я пытаюсь добиться следующего:
С вызывает ржавчинуrust перезванивает в c и регистрирует обратный вызов для заданного пользователем объекта чертыс вызывает ржавчину с контекстомrust вызывает обратный вызов в контексте (объект trait)Я немного поиграл с этим. Я получил довольно далеко, но все еще не совсем там.
Бит 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);
}
Немного ржавчины:
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);
}
}
Проблема:
Моя программа не работает, когда я пытаюсь вызвать «обратный вызов» для объекта черты в «rust_cb»Одно из решений: - Измените сигнатуру функции "rust_cb" на
pub extern fn rust_cb(context: *mut MyFoo)
но это не то, что я хочу, так как я пытаюсь создать безопасную оболочку, которая знает только черты слушателя
Любая помощь приветствуется
PS: я предполагаю, что это segfaults, потому что компилятор не знает смещения обратного вызова для черты Foo, ему нужен фактический объект, чтобы определить, где он находится. но тогда я понятия не имею, как обойти это