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

Rust与C# FFI互调时调用C#函数抛出System.AccessViolationException

Rust与C# FFI回调异常修复方案

错误根源

  1. 参数类型不匹配:C#传递的是函数指针(IntPtr),但Rust函数错误地将参数声明为&i8,导致内存解析完全错误,直接触发访问违规。
  2. 类型转换错误:用clone()和transmute处理函数指针的方式不符合C调用约定,进一步加剧内存访问问题。

修正后的代码

C# 代码

public class Program
{
    [DllImport("D:\\Misc. CSharp\\NativeTesting\\Rust\\target\\debug\\test.dll")]
    public static extern void Test(IntPtr function);

    public static void TestFunction()
    {
        Console.WriteLine("Test!");
    }
    
    public delegate void TestDelegate();
    
    public static void Main()
    {
        // 保留委托引用,避免被GC意外回收
        TestDelegate callback = TestFunction;
        Test(Marshal.GetFunctionPointerForDelegate(callback));
        Console.WriteLine("Done");
    }
}

Rust 代码(推荐写法)

#[no_mangle]
pub extern "C" fn Test(logger: extern "C" fn()) {
    // 直接调用符合C调用约定的函数指针
    logger();
}

Rust 代码(原始指针兼容写法)

如果需要更灵活的指针处理,也可以用原始指针转换:

#[no_mangle]
pub extern "C" fn Test(logger: *const ()) {
    unsafe {
        // 将原始指针转换为C调用约定的函数指针
        let callback: extern "C" fn() = std::mem::transmute(logger);
        callback();
    }
}

关键说明

  • 必须用extern "C"修饰Rust中的函数指针,确保和C# P/Invoke的默认调用约定一致。
  • 显式保留C#委托的引用是FFI回调的最佳实践,即使静态方法的委托被回收概率低,也能避免潜在的内存访问问题。
  • 参数类型严格匹配是FFI通信的核心,任何类型不匹配都会导致内存错误或程序崩溃。

内容的提问来源于stack exchange,提问作者Big_Bad_E

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 23:35:39