You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C#中调用参数包含函数类型的Rust导出函数

解决方案

问题原因

  • Rust的&dyn Fn是Rust特有动态分发trait对象,不兼容C ABI,无法和C#传递的非托管委托直接匹配
  • 原有尝试实现返回了栈上临时变量的可变指针,属于未定义行为,且返回值类型和C#声明的int类型不匹配

正确的Rust实现

第一步 调整Cargo.toml配置

首先修改配置确保编译出C兼容的动态库:

[package]
name = "rust_csharp_demo"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]

第二步 编写导出函数

使用C ABI兼容的函数指针类型替代&dyn Fn即可:

fn operation(number: i32, f: impl Fn(i32) -> i32) -> i32 {
    f(number)
}

#[no_mangle]
pub extern "C" fn c_operation(number: i32, f: extern "C" fn(i32) -> i32) -> i32 {
    // 外部传入的C兼容函数指针可直接作为Fn实现传入原有逻辑
    operation(number, f)
}

C#端适配(可选但推荐)

显式指定调用约定,避免不同平台默认规则不一致导致的栈异常:

const string RSTLIB = "../../PathOfDLL";

// 显式指定调用约定和Rust的extern "C"匹配
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int Fn(int number);

[DllImport(RSTLIB, CallingConvention = CallingConvention.Cdecl)]
static extern int c_operation(int x, Fn fn);

int Square(int number) => number * number;
int Cube(int number) => number * number * number;

void Test()
{
    Console.WriteLine("{0}", c_operation(5, Square)); // 输出25
    Console.WriteLine("{0}", c_operation(7, Square)); // 输出49
    Console.WriteLine("{0}", c_operation(3, Cube)); // 输出27
}

注意事项

  • 编译Rust库时注意和C#运行的平台保持一致,C#跑x86就编译Rust x86版本,跑x64就对应x64版本,否则会出现DLL加载失败问题
  • Linux/macOS平台需要把DLL路径替换为对应.so/.dylib文件的路径

内容的提问来源于stack exchange,提问作者Alexandra Danith Ansley

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 03:45:08