将 C# 实例方法作为回调传递给 Rust?

Shm*_*opy 5 c# rust

我正在尝试将 C# 方法传递给 Rust 以用作回调。我已经成功地传递了一个静态函数并且它工作正常(见下文)。

现在我想调用一个实例方法,这意味着trigger下面的函数也应该接收一个不透明的 ( libc::c_void) this 指针。我怎样才能得到哪个IntPtrRust应该作为实例指针传递给回调函数?

C#

    class Program
    {
        delegate void PrintFn(int x);

        public static void Main(string[] args)
        {
            PrintFn fn = Print;
            var ptr = Marshal.GetFunctionPointerForDelegate(fn);
            IntPtr handle = IntPtr.Zero;
            create(ptr, out handle);
            trigger(handle, 3);
        }

        public static void Print(int x)
        {
            Console.WriteLine($"C#: {x}");
        }

        [DllImport(@"/path/to/rust/dll")]
        public static extern int create(IntPtr readFn, out IntPtr callback);

        [DllImport(@"/path/to/rust/dll")]
        public static extern int trigger(IntPtr handle, int x);
    }
Run Code Online (Sandbox Code Playgroud)

锈:

use std::boxed::Box;

pub struct RustCallback {
    callback: extern "stdcall" fn(i32),
}

impl RustCallback {
    fn new(callback: extern "stdcall" fn(i32)) -> RustCallback {
        RustCallback {
            callback: read_fn,
        }
    }
}

pub fn set_output_arg<T>(out: *mut T, value: T) {
    unsafe { *out.as_mut().unwrap() = value };
}

#[no_mangle]
pub extern "C" fn create(callback: extern "stdcall" fn(i32), sc: *mut *mut RustCallback)  -> u32 {
    set_output_arg(sc, Box::into_raw(Box::new(RustCallback::new(callback))));
    0
}

#[no_mangle]
pub extern "C" fn trigger(sc: *mut RustCallback, x: i32)  ->  u32 {
    let sc = unsafe { sc.as_mut().unwrap() };
    let f = sc.read_fn;
    f(x);
    0
}
Run Code Online (Sandbox Code Playgroud)

Ale*_*ley 1

我正在处理相同的代码。我找到了一种比你公开的更简单的方法,看:

\n
fn operation(number: i32, f: &dyn Fn(i32) -> i32) {\n    f(number);\n}\n#[no_mangle]\nfn print(number: i32) {\n    println!("Rust: {}", number);\n}\n#[no_mangle]\npub extern "C" fn c_print(number: i32, callback: unsafe extern "C" fn(i32) -> i32) {\n    operation(number, &|n| unsafe { callback(n) });\n}\n
Run Code Online (Sandbox Code Playgroud)\n

然后,在 C# 中:

\n
delegate void PrintFn(int number);\n\npublic static void Run()\n{\n    int number = 1234;\n\n    // passing a C# function as parameter of Rust function\n    c_print(number, Print);\n\n    // passing a Rust function as callback inside the same Rust function\n    print(number);\n}\n\nstatic void Print(int number)\n{\n    Console.WriteLine($"C#: {number}\\n");\n}\n\n[DllImport(RLIB)] static extern void c_print(int number, PrintFn fn);\n[DllImport(RLIB)] static extern void print(int number);\n
Run Code Online (Sandbox Code Playgroud)\n

当我开始处理这个问题时,请查找:\xc2\xabHow to use from C# a Rust function that has another function as a argument?\xc2\xbb

\n