0

我正在尝试在 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);
4

3 回答 3

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

编辑

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

于 2009-02-16T18:29:46.520 回答
0

您的回调应如下所示:

Public Delegate Sub AlertManCallbackDel(ByRef data As Byte)

这样做的原因是您通过引用传递了一个单字节值。

至于非托管函数的声明,应该是这样的:

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

请注意,返回类型是整数,在 VB.NET 中是 32 位值。在 VB6 中,Long 是一个 32 位的值,因此需要在 VB.NET 中进行更改。

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

于 2009-02-16T19:15:45.847 回答
0

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

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

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

更新:

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

于 2009-02-16T19:17:01.260 回答