C# 如何使用委托参数类型定义ePinVokeMethod?

C# 如何使用委托参数类型定义ePinVokeMethod?,c#,pinvoke,C#,Pinvoke,我有一个方法,可以动态生成p/Invoke函数: member private this.MakePInvokeMethod(dllName:string, entryName:string, callingConvention:CallingConventions, returnType:Type, parameterTypes:Type[],

我有一个方法,可以动态生成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
,则在生成p/Invoke方法时出现异常:

System.Runtime.InteropServices.MarshalDirectiveException : Cannot marshal 'parameter #4': Generic types cannot be marshaled.

有什么解决办法吗?在普通的P/Invoke中,您可以添加
[marshallas(UnmanagedType.FunctionPtr)]
将委托转换为函数指针,但如何使用动态P/Invoke方法生成?

正如@xanatos所建议的,我找到了一个解决方法。函数指针可以简单地替换为

IntPtr
,然后使用
Marshal.GetFunctionPointerForDelegate
。需要注意的一点是,委托不能是泛型的,这意味着您不能使用
Func
,相反,您需要自己定义一个非泛型委托类型,并通过与medthod一起创建一个新委托类型来使用它。

。Sadlyt,您不能使用<代码>动作<代码>或<代码> FUNC。另一种选择是简单地将函数指针视为<代码> ItPTR 但是,您只是在移动与
操作
/
Func
具有相同限制的
marshall.GetFunctionPointerForDelegate
上的问题,有更简单的方法来控制DLL路径,例如
LoadLibrary
在使用任何pinvoke之前控制DLL。@xanatos我知道这一点
LoadLibrary
解决方案,它在Windows上运行良好,但在Linux/Mono上不起作用,
dlopen
不会缓存dll。