我正在尝试将一个C#方法传递给Rust以用作回调 . 我设法传递一个静态函数,它工作正常(见下文) .

现在我想调用一个实例方法,这意味着下面的 trigger 函数也应该接收一个不透明( libc::c_void )这个指针 . 如何获取Rust应该作为回调函数的实例指针传递的 IntPtr

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);
    }

锈:

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
}