2009-02-16 101 views
0

我想在VB.NET中使用非託管的DLL。隨DLL提供的示例源代碼在VB6中,下面是我將它轉換爲.NET的嘗試。當DLL試圖做回調時,我得到一個「試圖讀取或寫入受保護的內存」異常。我真的不關心實際調用的回調函數。 我的代碼:在VB .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); 

回答

2

你能張貼AlertManC原來的本地definiton?

我的猜測雖然是回調函數的數據參數實際上是一個整數與長。在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 

編輯

我更新根據您發佈的原生簽名的代碼。你可以試試這個嗎?

+0

謝謝,你搖滾!將長變爲整數是問題!你的原始解決方案也會有效。實際上,爲了簡潔起見,我刪除了另外7個參數(我對此感到羞恥)。把它們切換到整數是個訣竅。 – Michael 2009-02-16 19:16:19

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中進行更改。

回調定義對於順利獲得也很重要,順便說一句。

+0

添加ByRef字節有潛在危險。想象一下,如果本機代碼傳遞NULL,會發生什麼。我認爲CLR在這種情況下會產生一個異常,因爲默認情況下ByRef是兩種編組方式。 – JaredPar 2009-02-16 19:23:58

0

如果回調的調用約定是cdecl,那麼您不能直接在C#或VB.NET中執行該操作。

您必須修改代理的IL才能正常運行。

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

更新:

我想不是正確的答案:)但會留下我的迴應。