Rust FFI将trait对象作为上下文传递给调用回调

Rust FFI将trait对象作为上下文传递给调用回调,第1张

概述好的,我正在尝试实现以下目标: > C召唤生锈 > rust回调c并在用户定义的trait对象上注册回调 > c调用上下文生锈 > rust调用上下文的回调(trait对象) 我一直在玩它很多.我走得很远,但仍然没有那么远. C位: #include <dlfcn.h>#include <stdio.h>void *global_ctx;void c_function(void* ctx 好的,我正在尝试实现以下目标:

> 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对象作为上下文传递给调用回调所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1216969.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-05
下一篇 2022-06-05

发表评论

登录后才能评论

评论列表(0条)

保存