如何使用委托参数类型定义PInvokeMethod?
问题描述:
我有一个方法,该方法产生P /动态调用函数:如何使用委托参数类型定义PInvokeMethod?
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>
,而是你需要自己定义一个非泛型的委托类型并使用它。
通过与方法一起创建新的委托类型。可悲的是你不能使用'Action '或'Func '。 – xanatos
另一种方法是简单地将函数指针视为一个'IntPtr',但那么你只是将'Marshal.GetFunctionPointerForDelegate'与'Action ''''Func ''具有相同的限制'' – xanatos
是更容易的方法来控制DLL路径 –