cxx icon indicating copy to clipboard operation
cxx copied to clipboard

Added support for std::function

Open paandahl opened this issue 2 years ago • 4 comments

I put this up as a draft to get feedback; the code still needs cleanup / documentation.

I have added support for std::function, with the following interface:

#[cxx::bridge]
pub mod ffi {
    pub struct CallbackArgs<'a>(
        u8,
        &'a Vec<u8>,
        Box<OpaqueStruct>,
    );
    
    extern "Rust" {
        type OpaqueStruct;
        unsafe fn t_take_ref_func_single_arg<'a>(f: &CxxFunction<&'a OpaqueStruct, ()>);
        fn t_take_ref_func_multi_arg(f: &CxxFunction<CallbackArgs, u16>);
    }
}

unsafe fn t_take_ref_func_single_arg<'a>(f: &CxxFunction<&'a OpaqueStruct, ()>) {
    f.call(&OpaqueStruct { ... });
}

fn t_take_ref_func_multi_arg(f: &CxxFunction<ffi::CallbackArgs, u16>) {
    let ret = f.call(
        ffi::TestArgs(
            2,
            vec![42],
            Box::new(OpaqueStruct { ... }),
        )
    );
}

Usage from C++:

t_take_ref_func_single_arg([&](const OpaqueStruct& arg) {
    ...
});

t_take_ref_func_multi_arg([&](
    uint8_t arg,
    rust::Vec<uint8_t> arg2,
    rust::Box<OpaqueStruct> arg3
) {
    ...
    return (uint16_t)200;
});

Explanation

The CxxFunction<A, R> takes two template arguments.

  • A - the arguments. Can be one of:
    1. A shared or opaque Rust type that is declared in the crate
    2. A tuple struct (most internal types supported)
  • R - the return type.

If A is a tuple struct, the contents will be spread out, so that each element will match a function argument. The tuple struct itself evaporates at the language boundary.

The callback can also be passed by value, wrapped in a UniquePtr.

Rationale

I wanted the API to resemble those of CxxVector, UniquePtr, etc. The tuple struct is not ideal, but necessary to allow for multiple arguments.

I considered looking into a wrapper that would expose the callback as a Fn trait object, but that seems out of line with the rest of the API.

Possible improvements

  • The code can probably be simplified / cleaned up a bit more
  • Some things are skipped for now - checking-logic, documentation, etc.

Discussion

How was this functionality imagined? Is this the way to go, or are there better ways to solve the problem at hand?

Closes: #52

paandahl avatar Sep 21 '22 12:09 paandahl

This is impeccable timing as I was just trying to implement C++ callbacks called from Rust.

casimcdaniels avatar Sep 21 '22 21:09 casimcdaniels

Hey all! Is there a status update on this feature?

kdewald avatar Dec 26 '22 04:12 kdewald

Hello everyone, is this feature going to be merged. ? :) @dtolnay @paandahl

We are looking into CXX at https://easymile.com/ and we'd love to use it and possibly contribute if there are things we can do.

Thanks!

noufelez avatar Feb 24 '23 15:02 noufelez

It has been a few months and just wanted to check if there was any update. This would be super helpful.

owenshoemaker avatar Oct 03 '23 20:10 owenshoemaker