ralfbiedert / interoptopus

The polyglot bindings generator for your library (C#, C, Python, …) 🐙
MIT License
315 stars 27 forks source link

Can't return a function as a named "callback!" from Rust #108

Open fakkoweb opened 1 month ago

fakkoweb commented 1 month ago

I am in a situation where I cannot figure out how to have a function to return a named callback type.

Somewhere in my internal Rust code I will have something like:

extern "C" fn exposed_sum(x:i32, y:i32) -> i32 {
    x + y
}

Naturally, I would expose it like this:

#[ffi_function]
#[no_mangle]
pub extern "C" fn rust_to_csharp() -> extern fn(x: i32, y: i32) -> i32 {
    exposed_sum // return rust method
}

but this gets me a Unsupported type at interface boundary found for rval: [.....] error.

Doing the following solves the issue, but on the C# side generates a name for the delegate that is not "SumDelegate":

// Define the function pointer type
type SumDelegate = extern "C" fn(i32, i32) -> i32;

// exposing a Rust callback that can be called from outside
#[ffi_function]
#[no_mangle]
pub extern "C" fn rust_to_csharp() -> SumDelegate {
    exposed_sum
}

However, if I do this instead to keep the naming I want:

callback!(SumDelegate(x: i32, y: i32) -> i32);

// exposing a Rust callback that can be called from outside
#[ffi_function]
#[no_mangle]
pub extern "C" fn rust_to_csharp() -> SumDelegate {
    exposed_sum
}

I cannot get it to compile in any way, because "exposed_sum" is not compatible with the SumDelegate type: expected SumDelegate, but found fn(i32, i32) -> i32 {exposed_sum}

Am I missing something?

ralfbiedert commented 1 month ago

I haven't used that feature in a while, but can you try


// exposing a Rust callback that can be called from outside
#[ffi_function]
#[no_mangle]
pub extern "C" fn rust_to_csharp() -> SumDelegate {
    SumDelegate(Some(exposed_sum))
}

Technically just exposed_sum.into() should work, but apparently it doesn't.