泛型类中获取委托函数指针用于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
相关产品推荐
相关产品推荐

