2016-02-26 64 views
-1

我有一个方法,该方法产生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方法生成?

+0

通过与方法一起创建新的委托类型。可悲的是你不能使用'Action <>'或'Func <>'。 – xanatos

+0

另一种方法是简单地将函数指针视为一个'IntPtr',但那么你只是将'Marshal.GetFunctionPointerForDelegate'与'Action <>''''Func <>''具有相同的限制'' – xanatos

+0

是更容易的方法来控制DLL路径 –

回答

0

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