如何让C#提供回调函数,给Rust编写的DLL调用

前情提要:
如何用C#调用RUST的DLL
C#从C/RUST DLL接口获取数组/字符串数据

前面研究过了基础的rust提供dll给C#使用的一些操作,这篇文章就是介绍如何在C#中声明回调函数,提供给rust端来进行调用

基本概念如下:

  • 回调函数(C#端编写)
  • DLL(Rust编写)
  • C#代码调用DLL中的函数,将回调函数作为参数传入,配置回调函数
  • 然后再Rust代码中,调用回调函数

rust端代码

rust这边的代码和正常写区别不大,我们假设传入了一个回调函数(fn(i32)类型),然后单独开一个线程每秒钟触发一次

use std::{thread, time::Duration};

#[no_mangle]
pub extern fn setCb(cb: extern fn(i32)) {
    thread::spawn(move || {
        let mut count = 0;
        loop {
            count+=1;
            cb(count);
            thread::sleep(Duration::from_secs(1));
        }
    });
}

C#端代码

和之前正常代码的唯一区别就是,需要新建一个独立的回调函数类型,类型声明如下:

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void DllcallBack(int data);

接着声明dll函数的时候,传入类型用上面声明的类型即可

[DllImport("csharpdll.dll", CallingConvention = CallingConvention.Cdecl)]
static extern void setCb(DllcallBack cb);

最后主代码直接调用

var cb = new DllcallBack((data) => Console.WriteLine($"trigger from rust {data}"));
setCb(cb);
//等待,防止软件运行完退出
Console.ReadLine();

运行效果

正常运行即可查看到预期效果:

trigger from rust 1
trigger from rust 2
trigger from rust 3
trigger from rust 4
trigger from rust 5
trigger from rust 6
...

小改测试回调返回值

可以在c#回调函数中再返回一个结果,看看rust是否可以接收到

use std::{thread, time::Duration};

#[no_mangle]
pub extern fn setCb(cb: extern fn(i32) -> i32) {
    thread::spawn(move || {
        let mut count = 0;
        loop {
            count+=1;
            let r = cb(count);
            println!("rust read cb return: {}", r);
            thread::sleep(Duration::from_secs(1));
        }
    });
}
class Program
{
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate int DllcallBack(int data);


    [DllImport("csharpdll/target/debug/csharpdll.dll", CallingConvention = CallingConvention.Cdecl)]
    static extern void setCb(DllcallBack cb);

    static void Main(string[] args)
    {
        var cb = new DllcallBack(
            (data) =>
            {
                Console.WriteLine($"trigger from rust {data} * 2 ↓");
                return data * 2;
            });
        setCb(cb);

        Console.ReadLine();
    }
}

运行结果:

trigger from rust 1 * 2 ↓
rust read cb return: 2
trigger from rust 2 * 2 ↓
rust read cb return: 4
trigger from rust 3 * 2 ↓
rust read cb return: 6
trigger from rust 4 * 2 ↓
rust read cb return: 8
trigger from rust 5 * 2 ↓
rust read cb return: 10
trigger from rust 6 * 2 ↓
rust read cb return: 12

发表评论

您的电子邮箱地址不会被公开。