-
Notifications
You must be signed in to change notification settings - Fork 396
Open
Description
What I got to work:
// lib.rs
#[cxx::bridge]
mod ffi {
#[derive(Debug)]
enum ClosureArg {
Yes,
No,
}
extern "Rust" {
type ClosureBridge;
fn call(&self, arg: ClosureArg);
}
unsafe extern "C++" {
include!("bridge/cpp/lib.hpp");
fn receive_closure(callback: Box<ClosureBridge>);
}
}
pub use ffi::{ClosureArg, receive_closure};
pub struct ClosureBridge(Box<dyn Fn(ClosureArg)>);
impl ClosureBridge {
fn call(&self, arg: ClosureArg) {
(self.0)(arg);
}
}
pub fn pass_closure(callback: impl Fn(ClosureArg) + 'static) {
receive_closure(Box::new(ClosureBridge(Box::new(callback))));
}// test.rs
use bridge::pass_closure;
fn main() {
let x = 1;
pass_closure(move |arg| {
println!("Closure {x} called with arg: {arg:?}");
})
}// lib.hpp
#pragma once
#include "rust/cxx.h"
#include "bridge/lib.rs.h"
void receive_closure(rust::Box<ClosureBridge> closure) {
closure->call(ClosureArg::Yes);
}This is very verbose, has a lot of scaffolding functions that are annoying to debug when compilation fails, and includes double boxing (box of Fn inside box of helper class). Is there a better way?
Metadata
Metadata
Assignees
Labels
No labels