我已经看过了rust foreign function interface个,并且成功地(并且很高兴地)可以从我的 rust 迹代码中调用一个c库.

然而,在c代码范围内,我似乎找不到有关如何注册回调以调用rust代码的任何细节.

这可能吗?

作为"你为什么要这么做"的理由;具体地说,我正在研究在rust应用程序中嵌入lua或python,并为在嵌入式运行时上运行的脚本公开一个脚本api.

调用这些内容大致如下:

  • 主要应用载荷
  • 应用程序使用ffi初始化脚本运行时
  • Application binds local rust functions to C-callbacks
  • 应用程序调用ffi将C回调绑定到脚本层
  • 应用程序运行~
  • 定期使用ffi触发脚本运行时以执行字节码块
  • 脚本代码执行各种琐碎的逻辑并调用绑定句柄
  • 绑定句柄调用c代码
  • The bound c code invokes local rust code

所有这些步骤,除了粗体的那些,我已经成功地开始工作,并且我已经使用调度器完成了一些琐碎的工作,C回调将"run me"命令转储到队列中,当控制返回到rust作用域时,应用程序查询队列并运行其中的命令...

...但从脚本方面来看,这有点尴尬,因为它意味着多个嵌套的异步回调,而脚本层的重点是简化需要进入脚本层的代码.

推荐答案

是的,您可以将一个回调函数从Rust传递到C并在那里调用它.

未经测试的示例(此处没有Rust编译器):

rust 面:

extern "C" fn callback(a:i32) {
    println!("I'm called from C with value {0}", a);
}

#[link(name = "mylib")]
extern {
   fn register_callback(cb: extern "C" fn(i32)) -> i32;
}

fn main() {
    unsafe {
        register_callback(callback);
    }
    ...
}

C方:

typedef void (*rust_callback)(int32_t);
rust_callback cb;

int32_t register_callback(rust_callback callback) {
    cb = callback;
    return 1;
}

void thread() {
  // do sth
  cb(xyz);
}

Rust相关问答推荐

如何优化小型固定大小数组中的搜索?

把Vector3变成Vector4的绝妙方法

如何访问Rust存储值的内存地址

文档示例需要导入相关的 struct ,但仅在运行测试时.这是故意的行为吗?

为什么Rust函数的移植速度比C++慢2倍?

如何为 struct 字段设置新值并在Ruust中的可变方法中返回旧值

带参考文献的 rust 元组解构

有没有一种惯用的方法来判断VEC中是否存在变体?

作为1字节位掩码的布尔值 struct

Rust ndarray:如何从索引中 Select 数组的行

Rust面向对象设计模式

`UnsafeCell` 在没有锁定的情况下跨线程共享 - 这可能会导致 UB,对吗?

当推送到 HashMap 中的 Vector 时,类型 `()` 无法取消引用

为什么在 macOS / iOS 上切换 WiFi 网络时 reqwest 响应会挂起?

第 7.4 章片段中如何定义 `thread_rng`

`map` 调用在这里有什么用吗?

在 Rust 中退出进程

在 Rust 中获得准确时间的正确方法?

如果我立即等待,为什么 `tokio::spawn` 需要一个 `'static` 生命周期?

如何将 u8 切片复制到 u32 切片中?