如何使用委托参数类型DefinePInvokeMethod?

时间:2016-02-26 08:49:14

标签: c# pinvoke

我有一个方法,可以动态生成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方法生成呢?

1 个答案:

答案 0 :(得分:0)

根据@xanatos的建议,我找到了解决方法。可以使用IntPtr简单地替换函数指针,然后使用Marshal.GetFunctionPointerForDelegate。需要注意的一点是,委托不能是通用的,这意味着您不能使用Func<int, IntPtr>,而是需要自己定义非泛型委托类型并使用它。