Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 将委托传递给泛型函数,然后封送。GetDelegateForFunctionPointer()_.net_Vb.net_Generics_Delegates_Unmanaged - Fatal编程技术网

.net 将委托传递给泛型函数,然后封送。GetDelegateForFunctionPointer()

.net 将委托传递给泛型函数,然后封送。GetDelegateForFunctionPointer(),.net,vb.net,generics,delegates,unmanaged,.net,Vb.net,Generics,Delegates,Unmanaged,我想编写一个通用的、可重用的函数,以便于在本机dll中调用导出函数并返回函数的返回值 考虑我的以下方法: Shared Function CallNativeFunction(Of TResult)( ByVal filepath As String, ByVal functionName As String,

我想编写一个通用的、可重用的函数,以便于在本机dll中调用导出函数并返回函数的返回值

考虑我的以下方法:

Shared Function CallNativeFunction(Of TResult)(
                                   ByVal filepath As String,
                                   ByVal functionName As String,
                                   ByVal functionSignature As [Delegate]) As TResult

    Dim hLib As IntPtr = NativeMethods.LoadLibrary(filepath)
    If (hLib = IntPtr.Zero) Then
        Throw New Win32Exception(Marshal.GetLastWin32Error())
    End If

    Dim dllEntryPoint As IntPtr = NativeMethods.GetProcAddress(hLib, functionName)
    If (dllEntryPoint = IntPtr.Zero) Then
        Throw New Win32Exception(Marshal.GetLastWin32Error())
    End If

    functionSignature = 
        Marshal.GetDelegateForFunctionPointer(dllEntryPoint, GetType([Delegate]))

    Dim result As TResult = 
        Conversion.CTypeDynamic(Of TResult)(functionSignature)

    Return result

End Function
或者也可以使用此备选签名:

Shared Function CallNativeFunction(Of TResult, TDelegate)(
                                   ByVal filepath As String,
                                   ByVal functionName As String,
                                   ByVal functionSignature As TDelegate) As TResult

...
好吧,我正在绞尽脑汁,试图找出目前定义函数类型参数的最佳方法,以及如何将正确的参数传递给函数以使其按预期工作。 现在它没有像预期的那样工作;当我将
[Delegate]
传递给函数时,对
GetDelegateForFunctionPointer
的调用抛出一个
参数异常
,表示参数必须派生自
[Delegate]
类型,如果我传递
Func(of T)
,则表示该类型不能是泛型类型

因此,假设我想调用在本机dll中导出的“DllRegisterServer”,以完成该任务,我应该编写以下代码:

<UnmanagedFunctionPointer(CallingConvention.StdCall)>
Friend Delegate Function PointerToMethodInvoker() As Integer

Sub CallNativeFunction(...)
    ' non-relevant code here ...
    ' ...
    Dim invoker As PointerToMethodInvoker = 
        Marshal.GetDelegateForFunctionPointer(Of PointerToMethodInvoker)(dllEntryPoint)

    Dim result As Integer = invoker()
End Sub

友元委托函数指针TomethodInvoker()为整数
子CallNativeFunction(…)
'此处的非相关代码。。。
' ...
作为指针的Dim调用程序MethodInvoker=

Marshal.GetDelegateForFunctionPointer(指针式MethodInvoker的)(DLLentPoint) Dim结果为整数=invoker() 端接头
…但该代码是硬编码的,委托是在类级别和
CallNativeFunction
块内定义的,我必须知道要继续定义的委托的确切名称。我想避免/简化这些事情。我的目的是将代码示例转换为可重用函数,以便能够传递非硬编码的
[Delegate]


我的问题是:如何调整当前代码以满足我解释的预期行为?

我编写了一个临时解决方案。这并不像我希望的那样通用,但总有比没有好的地方,我认为在使用此函数时,可以节省大量代码,而不会损失太多的灵活性/效率和错误处理。我不确定的一件事是,当有两个定义了相同名称但签名不同的导出时,如何处理歧义消除

如果有人有比我更好的方法,那么请公布答案。我不会接受我自己的答案。谢谢你在我问题的评论框中给我带来的帮助、提示和/或建议

我写了两个函数,一个用于让本机函数传递一个委托(这样最终用户可以对返回的委托做任何他想做的事情),另一个用于执行函数,它的编写理念是:“轻松地完成此任务,对我来说没有任何困难”,我知道这并不太安全,但是。。。这只是一个简单的辅助方法

我希望这段代码对某些特定场景中的人有用。使用示例写在XML文档中。该代码缺少一些必需的Windows API定义,以避免生成过大的代码,我认为这就足够了,每个人都可以在上查找必需的定义


GetNativeFunction
调用函数
Marshal.GetDelegateForFunctionPointer(dllEntryPoint,functionSignature.GetType())@Hans Passant感谢您提供了这一技巧,但也许我问得太多了,您是否可以提供一个示例,说明如何(在方法块内部)声明从[Delegate]派生的工作/可接受对象为了能够将它传递给我的函数,我将分享几分钟前编写的一段代码,以显示一个有效的声明和一个无效的声明:问题是,我需要避免在类级别声明委托,因此我正在试图找出如何使它在无效的代码中工作。不起作用的代码在调用GetDelegateForFunctionPointer时引发异常,并指出:“指定的类型不能是泛型类型定义”……此方法中的一个非常基本的缺陷是它无法将任何参数传递给本机函数。它缺少一个Params Object()参数,即可以传递给Delegate.DynamicInvoke()的参数。因此,委托类型只能是Func(属于TResult)。不,您必须确定TResult是什么,这样只有Func(整数)可以工作。不,委托类型不能是泛型类型参数。使其过于通用并不是很有用,也没有有意义的类型检查,而且出错总是会产生异常。
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets a function exported in a native dll.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <example> This is a code example.
''' <code>
''' Public Module Module1
''' 
'''     ''' ----------------------------------------------------------------------------------------------------
'''     ''' &lt;summary&gt;
'''     ''' A delegate to call DllRegisterServer or DllUnregisterServer functions in a native dll.
'''     ''' &lt;/summary&gt;
'''     ''' ----------------------------------------------------------------------------------------------------
'''     ''' &lt;returns&gt;
'''     ''' The result of calling DllRegisterServer or DllUnregisterServer functions in a native dll.
'''     ''' &lt;/returns&gt;
'''     ''' ----------------------------------------------------------------------------------------------------
'''     &lt;UnmanagedFunctionPointer(CallingConvention.StdCall)&gt;
'''     Friend Delegate Function PointerToRegistrationMethodInvoker() As Integer
''' 
'''     Public Sub Main()
''' 
'''         Dim methodInvoker As PointerToRegistrationMethodInvoker =
'''                 GetNativeFunction(Of PointerToRegistrationMethodInvoker)("C:\native.dll", "DllRegisterServer")
''' 
'''         Dim result As Integer = methodInvoker.Invoke()
'''         If (result &lt;&gt; 0) Then
'''             ' ToDo: Handle specific errors...
'''         End If
''' 
'''     End Sub
''' 
''' End Module
''' </code>
''' </example>
''' ----------------------------------------------------------------------------------------------------
''' <typeparam name="TDelegate">
''' The <see cref="Type"/> of the source <see cref="[Delegate]"/> 
''' that will represent the signature of the native function.
''' </typeparam>
'''  
''' <param name="filepath">
''' The file path of the native dll.
''' </param>
''' 
''' <param name="functionName">
''' The name of the function to be retrieved.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' The resulting <see cref="[Delegate]"/> which represents a pointer to the method invoker.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<DebuggerStepThrough>
Public Shared Function GetNativeFunction(Of TDelegate)(ByVal filepath As String,
                                                       ByVal functionName As String) As TDelegate

    Dim hLib As IntPtr
    Dim win32err As Integer

    hLib = NativeMethods.LoadLibrary(filepath)
    win32err = Marshal.GetLastWin32Error()
    If (hLib = IntPtr.Zero) Then
        If (win32err = Win32ErrorCode.ERROR_BAD_EXE_FORMAT) Then ' 193
            Throw New BadImageFormatException("Failed to load library.", filepath)
        ElseIf (win32err = Win32ErrorCode.ERROR_MOD_NOT_FOUND) Then ' 126
            Throw New FileNotFoundException("File not found.", filepath)
        Else
            Throw New Win32Exception(win32err)
        End If
    End If

    Dim dllEntryPoint As IntPtr = NativeMethods.GetProcAddress(hLib, functionName)
    win32err = Marshal.GetLastWin32Error()
    If (dllEntryPoint = IntPtr.Zero) Then
        If (win32err = Win32ErrorCode.ERROR_PROC_NOT_FOUND) Then ' 127
            Throw New EntryPointNotFoundException(String.Format("Failed to get entry point: '{0}'", functionName))
        Else
            Throw New Win32Exception(win32err)
        End If
    End If

    Return Marshal.GetDelegateForFunctionPointer(Of TDelegate)(dllEntryPoint)

End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Executes a function exported in a native dll and returns the result value.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <example> This is a code example.
''' <code>
''' Public Module Module1
''' 
'''     ''' ----------------------------------------------------------------------------------------------------
'''     ''' &lt;summary&gt;
'''     ''' A delegate to call DllRegisterServer or DllUnregisterServer functions in a native dll.
'''     ''' &lt;/summary&gt;
'''     ''' ----------------------------------------------------------------------------------------------------
'''     ''' &lt;returns&gt;
'''     ''' The result of calling DllRegisterServer or DllUnregisterServer functions in a native dll.
'''     ''' &lt;/returns&gt;
'''     ''' ----------------------------------------------------------------------------------------------------
'''     &lt;UnmanagedFunctionPointer(CallingConvention.StdCall)&gt;
'''     Friend Delegate Function PointerToRegistrationMethodInvoker() As Integer
''' 
'''     Public Sub Main()
''' 
'''         Dim result As Integer = 
'''             CallNativeFunction(Of Integer, PointerToRegistrationMethodInvoker)(filepath, "DllRegisterServer", Nothing)
''' 
'''         Dim result As Integer = methodInvoker.Invoke()
'''         If (result &lt;&gt; 0) Then
'''             ' ToDo?: Handle specific errors...
'''         End If
''' 
'''     End Sub
''' 
''' End Module
''' </code>
''' </example>
''' ----------------------------------------------------------------------------------------------------
''' <typeparam name="TResult">
''' The <see cref="Type"/> of the value returned by the native function.
''' </typeparam>
'''  
''' <typeparam name="TDelegate">
''' The <see cref="Type"/> of the source <see cref="[Delegate]"/> 
''' that will represent the signature of the native function.
''' </typeparam>
'''
''' <param name="filepath">
''' The file path of the native dll.
''' </param>
''' 
''' <param name="functionName">
''' The name of the function to be executed.
''' </param>
''' 
''' <param name="functionSignature">
''' A <see cref="[Delegate]"/> that will represent the signature of the native function.
''' </param>
''' 
''' <param name="parameters">
''' An argument list for the invoked function. 
''' This is an array of objects with the same number, order, and type as the parameters of the function to be invoked.
''' <para></para>
''' If there are no parameters, parameters should be null.If the method
''' Any object in this array that is not explicitly initialized with a value will contain the default value for
''' that object type. 
''' <para></para>
''' For reference-type elements, this value is <see langword="Nothing"/>. 
''' For value-type elements, this value is 0, 0.0, or false, depending on the specific element type.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' The result of calling the native function.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<DebuggerStepThrough>
Public Shared Function CallNativeFunction(Of TResult, TDelegate)(ByVal filepath As String,
                                                                 ByVal functionName As String,
                                                                 ByVal functionSignature As TDelegate,
                                                                 ByVal ParamArray parameters As Object()) As TResult

    functionSignature = GetNativeFunction(Of TDelegate)(filepath, functionName)

    Dim methodInvoker As MulticastDelegate = Conversion.CTypeDynamic(Of MulticastDelegate)(functionSignature)
    Dim result As TResult = CType(methodInvoker.DynamicInvoke(parameters), TResult)
    Return result

End Function