如何使用委托参数类型定义 PInvoke方法
本文关键字:定义 PInvoke 方法 类型 参数 何使用 | 更新日期: 2023-09-27 18:36:15
我有一个方法,它可以动态生成 P/Invoke 函数:
member private this.MakePInvokeMethod(dllName:string, entryName:string, callingConvention:CallingConventions,
returnType:Type, parameterTypes:Type[],
nativeCallConv:CallingConvention, nativeCharSet:CharSet) =
let typeBuilder = moduleBuilder.DefineType("__Internal.DynamicInterop." + entryName)
let methodBuilder = typeBuilder.DefinePInvokeMethod("Invoke", dllName, entryName, MethodAttributes.Static ||| MethodAttributes.PinvokeImpl,
callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet)
methodBuilder.SetImplementationFlags(methodBuilder.GetMethodImplementationFlags() ||| MethodImplAttributes.PreserveSig)
typeBuilder.CreateType().GetMethod("Invoke", BindingFlags.Static ||| BindingFlags.NonPublic)
原因是,我可以更轻松地控制 dll 路径。
但是现在我遇到了一个 C 函数,它使用函数指针:
CUresult cuOccupancyMaxPotentialBlockSize ( int* minGridSize, int* blockSize, CUfunction func, CUoccupancyB2DSize blockSizeToDynamicSMemSize, size_t dynamicSMemSize, int blockSizeLimit )
其中,类型 CUoccupancyB2DSize
是以下函数指针:
size_t(CUDA_CB* CUoccupancyB2DSize )( int blockSize )
因此,如果我将该类型转换为 Func<int, IntPtr>
,我在生成 P/Invoke 方法时出现异常:
System.Runtime.InteropServices.MarshalDirectiveException : Cannot marshal 'parameter #4': Generic types cannot be marshaled.
有什么解决方法吗?在普通的 P/Invoke 中,您可以添加 [MarshalAs(UnmanagedType.FunctionPtr)]
以将委托转换为函数指针,但是如何使用动态 P/Invoke 方法生成来做到这一点?
按照@xanatos的建议,我找到了解决方法。函数指针可以简单地替换为 IntPtr
,然后使用 Marshal.GetFunctionPointerForDelegate
。需要注意的一点是,委托不能是泛型的,这意味着你不能使用 Func<int, IntPtr>
,相反,你需要自己定义一个非泛型委托类型并使用它。