Rust FFI将trait对象作为上下文传递给调用回调
好的,我正在尝试实现以下目标:
> C召唤生锈 我一直在玩它很多.我走得很远,但仍然没有那么远. C位: #include <dlfcn.h> #include <stdio.h> void *global_ctx; void c_function(void* ctx) { printf("Called c_functionn"); global_ctx = ctx; } int main(void) { void *thing = dlopen("thing/target/debug/libthing.dylib",RTLD_NOW | RTLD_GLOBAL); if (!thing) { printf("error: %sn",dlerror()); return 1; } void (*rust_function)(void) = dlsym(thing,"rust_function"); void (*rust_cb)(void*) = dlsym(thing,"rust_cb"); printf("rust_function = %pn",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”中对特征对象调用“回调”时,我的程序会出现段错误 一解决方案: pub extern fn rust_cb(context: *mut MyFoo) 但这不是我想要的,因为我正在尝试创建一个只知道监听器特性的安全包装器 任何帮助赞赏 PS:我的假设是它是segfaults,因为编译器不知道特征Foo上的回调偏移量,它需要实际的对象来确定它的位置.但后来我不知道如何解决这个问题 解决方法
所以,如果你需要将Foo表示为void *,你可以使用:
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 Box<Foo>) { unsafe { let cb: Box<Box<Foo>> = Box::from_raw(context); cb.callback(); } } #[no_mangle] pub extern fn rust_function() { println!("Called rust_function"); let tmp: Box<Box<Foo>> = Box::new(Box::new(MyFoo)); unsafe { c_function(Box::into_raw(tmp) as *mut Box<Foo> as *mut libc::c_void); } } 我想你可能误解了特质对象是什么.特征对象是两个指针大小的类型(因此,64位系统上为128位).在这个例子中,Foo不是特征对象,它是动态大小的类型(即具有可变大小的类型,例如str).盒及LT;富>是一个特质对象.盒及LT;盒及LT;富>>既不是特征对象也不是动态大小的类型,它是一个与指针大小相同的类型,这就是为什么我们需要在这里使用它,因为我们想将它转换为void *. 我将其称为“泄漏”,因为当您调用Box :: into_raw时,您正在泄漏框中所有内容的内存,这意味着您负责确保调用析构函数(Drop实现). (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |