> C召唤生锈
> rust回调c并在用户定义的trait对象上注册回调
> 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上的回调偏移量,它需要实际的对象来确定它的位置.但后来我不知道如何解决这个问题
解决方法 所以,如果你需要将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实现).
总结以上是内存溢出为你收集整理的Rust FFI将trait对象作为上下文传递给调用回调全部内容,希望文章能够帮你解决Rust FFI将trait对象作为上下文传递给调用回调所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)