2016-02-26 70 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>,而是你需要自己定義一個非泛型的委託類型並使用它。