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

泛型类中获取委托函数指针用于P/Invoke时遇异常的解决办法

解决泛型类中委托获取函数指针的ArgumentException问题

你遇到的错误根源是:定义在泛型类内部的委托类型会被视为泛型关联类型(比如MyClass<int>.MyCompareCallback属于构造泛型类型的嵌套类型),而Marshal.GetFunctionPointerForDelegate明确要求传入的委托类型不能是泛型类型。

以下是两种可行的解决办法:

方案1:将委托定义移到泛型类外部(推荐)

把委托从泛型类中抽离,定义为顶级非泛型委托,这样委托类型本身与泛型无关,就能正常获取函数指针。同时必须注意保留委托的长期引用,避免GC回收导致原生调用时出现内存错误。

修改后的代码示例:

// 委托定义为顶级非泛型类型
private protected delegate int MyCompareCallback(int idxA, int idxB);

var c = new MyClass<int>();
c.DoWork();

public class MyClass<T> {
    // 用类成员变量持有委托,防止被GC回收
    private MyCompareCallback _sortCallback;

    private int SortCompareFunction(int idxA, int idxB) {
        return -1; // 简化实现
    }

    public void DoWork() {
        _sortCallback = SortCompareFunction;
        IntPtr callbackPtr = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate(_sortCallback);
        Console.WriteLine("Success");
    }
}

方案2:使用非泛型静态方法中转

如果必须将委托保留在泛型类内部,可以通过非泛型静态方法做中转,让委托指向非泛型关联的方法类型。

示例代码:

var c = new MyClass<int>();
c.DoWork();

public class MyClass<T> {
    private protected delegate int MyCompareCallback(int idxA, int idxB);
    // 持有委托引用,避免GC回收
    private MyCompareCallback _sortCallback;

    private int SortCompareFunction(int idxA, int idxB) {
        return -1;
    }

    // 非泛型静态包装方法,持有实例引用
    private static int StaticCompareWrapper(MyClass<T> instance, int idxA, int idxB) {
        return instance.SortCompareFunction(idxA, idxB);
    }

    public void DoWork() {
        // 委托指向静态方法,规避泛型类型限制
        _sortCallback = (idxA, idxB) => StaticCompareWrapper(this, idxA, idxB);
        IntPtr callbackPtr = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate(_sortCallback);
        Console.WriteLine("Success");
    }
}

关键注意事项

  • 无论采用哪种方案,都要确保委托实例不会被垃圾回收:如果委托是局部变量,DoWork方法执行完毕后GC可能会回收它,导致原生代码调用指针时崩溃。必须将委托存储在类成员变量或其他长期存在的引用中。
  • .NET Interop机制不支持直接使用泛型委托类型获取函数指针,必须通过上述方式规避泛型类型限制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 11:02:28