如何用C#调用RUST的DLL

最近(半年前)有项目需要使用c#调用rust的dll,所以研究了一下如何调用(其实就是C#效率太低了,为了提高效率才用的这个办法)

需要实现的操作:

  • c#调用RUST接口,传入int,不返回值
  • c#调用RUST接口,获取i32
  • C#传入byte数组

先新建一个rust项目:

cargo new csharpdll --lib

然后这里要注意,如果你是x64电脑,要编译x86的dll,那么需要按下面的步骤编译

rustup target add i686-pc-windows-msvc
cargo build --release --target=i686-pc-windows-msvc

另外,由于默认配置编译后会导致dll依赖vc库,我们需要配置打包静态库,参考:如何让RUST编译生成出不依赖VC++库的文件?

因为我追求让dll文件足够小,所以在Cargo.toml里加了下面的东西,这里按需使用了

[profile.release]
lto = true
strip = true
codegen-units = 1
panic = "abort"

接着我们编写一个c#调用RUST接口,不返回值的函数,这里注意,c#传入的int实际上就是i32

#[no_mangle]
pub extern fn func1(data:i32) {
    //balabala一堆代码
}

主要就是前一行的#[no_mangle]和函数前的pub extern,别的没什么好注意的

然后在C#中,只要这样声明就能调用了(注意C#的exe文件需要与dll同级,或者dll在环境变量path路径,并且C#的x64/x86需要与dll相匹配)

[DllImport("csharpdll.dll", CallingConvention = CallingConvention.Cdecl)]
static extern void func1(int data);

接着我们来写c#调用RUST接口,获取i32的接口,没啥特别的:

rust

#[no_mangle]
pub extern fn func2() -> i32 {
    123
}

C#

[DllImport("csharpdll.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int func2();

最后就是C#传入byte数组了,这里需要注意,必须传入长度

rust

#[no_mangle]
pub extern fn func3(ptr: *const u8, len: usize) {
    //获取到传入的数组
    let arr=unsafe{std::slice::from_raw_parts(ptr, len)};
    //balabala一堆代码
}

C#这边和之前也差不多

[DllImport("csharpdll.dll", CallingConvention = CallingConvention.Cdecl)]
static extern void func3(byte[] ptr, uint len);

发表评论

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