VB .NET中非托管DLL的回调函数

时间:2009-02-16 18:22:53

标签: vb.net dll interop unmanaged

我正在尝试在VB.NET中使用非托管DLL。随dll提供的示例源代码在VB6中,下面是我尝试将其转换为.NET。当dll尝试进行回调时,我得到“尝试读取或写入受保护的内存”异常。我真的不关心实际调用的回调函数。 我的代码:

<DllImport("AlertMan.dll")> _
Public Shared Function AlertManC( _
    ByVal CallbackAddr As AlertManCallbackDel) As Long
End Function

Public Delegate Sub AlertManCallbackDel(ByVal data As Long)

Public Sub AlertManCallback(ByVal data As Long)       
End Sub

Public mydel As New AlertManCallbackDel(AddressOf AlertManCallback)
'protected memeory exception here
Dim IStat as Long = AlertManC(mydel) 

原始VB6示例代码:

Declare Function AlertManC _
    Lib "AlertMan.dll" _
    Alias "AlertManC" (ByVal CallbackAddr As Long) As Long

Private Sub AlertManCallback(ByVal data As Long)
End Sub

' calling code
Dim IStat As Long
IStat = AlertManC(AddressOf AlertManCallBack)

原始dll标题

typedef void TACBFUNC(char *);
int AlertManC(TACBFUNC *WriteCaller cHANDLEPARM);

3 个答案:

答案 0 :(得分:2)

您可以发布AlertManC的原始原生定义吗?

我的猜测是回调函数的数据参数实际上是整数与长整数。在VB6中,我相信Long实际上只有32位而不是VB.Net,它们是64位。试试这个

   <DllImport("AlertMan.dll")> _
   Public Shared Function AlertManC(ByVal CallbackAddr As AlertManCallbackDel) As Long
   End Function

   Public Delegate Sub AlertManCallbackDel(ByVal data As IntPtr)


   Public Sub AlertManCallback(ByVal data As IntPtr)       
   End Sub

修改

我根据您发布的本机签名更新了代码。你能尝试一下吗?

答案 1 :(得分:0)

您的回调应如下所示:

Public Delegate Sub AlertManCallbackDel(ByRef data As Byte)

这是因为您通过引用传递单字节值。

对于非托管函数的声明,它应该如下所示:

<DllImport("AlertMan.dll")> _
Public Shared Function AlertManC( _
    ByVal CallbackAddr As AlertManCallbackDel) As Integer
End Function

请注意,返回类型是Integer,在VB.NET中是32位值。在VB6中,Long是32位值,因此需要更改VB.NET。

回调定义也很重要,顺便说一下,顺便说一句。

答案 2 :(得分:0)

如果回调的调用约定是cdecl,则无法直接在C#或VB.NET中执行此操作。

您必须修改委托的IL才能正常运行。

您可以在CodeProject上搜索深入的文章。

更新:

我猜不是正确答案:)但是会留下我的回复。