2012-06-28 126 views
1

我正在開發win32程序集中的串口dll(MASM32)。它有自己的線程檢查多個事件,並在指定的緩衝區閾值處通過調用回調函數通知託管的主應用程序。這只是一個沒有參數/返回值的調用。從非託管win32程序集DLL調用託管代碼 - 崩潰

在啓動時的主應用程序商店的回調函數的地址由DLL調用一個函數:

pCallBackFunction dd 0 

SetCallBackPointer proc pcb:DWORD 

mov eax, pcb 
mov pCallBackFunction, eax 
call DWORD ptr pCallBackFunction ; verify it immediately 
ret 

SetCallBackPointer endp 

上功能會立即回撥以覈實信息管理的應用程序回調例程。它工作正常。 但是,當我將調用指令放到dll中的其他函數時,它會使應用程序崩潰。無論該調用是在簡單函數中還是在dll的threadproc中都無關緊要。例如:

OpenPort proc pn:byte,br:dword, inputbuffersize: dword, outputbuffersize:dword, thresholdsize: dword 
LOCAL dcb: DCB 
LOCAL SerialTimeOuts: COMMTIMEOUTS 
call DWORD ptr pCallBackFunction 
xor eax, eax 
mov al, pn 
mov [com_port+3],al 

etc. etc. 

會在調用DWORD ptr pCallBackFunction時崩潰。由於我先調用SetCallBackPointer來在pCallBackFunction中存儲一個有效的地址,它應該有一個有效的地址。

我的管理應用程序是用C#和相關的部分是:

public partial class Form1 : Form 
{ 
    public delegate void CallBackDelegate(); 
    public static CallBackDelegate mydelegate; 

    [DllImport("serialport.dll")] 
    private static extern void SetCallBackPointer(CallBackDelegate Delegate); 

    [DllImport("serialport.dll")] 
    public static extern int OpenPort(byte com, uint br, uint inbufsize, uint outbufsize, uint threshsize); 



    public Form1() 
    { 

     InitializeComponent(); 



     mydelegate =new CallBackDelegate(CallbackFunction); 

     SetCallBackPointer(mydelegate); 

     unsafe 
     { 
      int sysstat; 
      int hResult; 

      hResult = OpenPort(Convert.ToByte('5'), 9600, 306, 4, 4); 
     } 
     } 

     public static void CallbackFunction() 
     { 
      MessageBox.Show("CallBack Function Called by Windows DLL"); 
     } 

的VS調試報道,該dll曾試圖讀/寫從/到受保護的內存地址。但是在調用SetCallBackPointer時,不存在這樣的問題。我在這裏做錯了什麼?

任何提示將是偉大的!

+0

如果您確信一切正確的是(pCallBackFunction不會被覆蓋)你檢查了調用約定(OpenPort有很多參數和返回值)嗎? –

+0

順便說一下...... + 1,因爲即使我無法確定原因,你仍然在組裝中寫作! –

+0

當我打電話給dword ...指令時,OpenPort工作正常。我將添加額外的函數來檢查是否覆蓋pCallBackFunction。 這只是練習,沒有真正的原因背後編寫彙編。謝謝。 – JustGreg

回答

0

SetCallBackDelegate必須使用IntPtr,而不是Delegate對象。

您必須使用Marshal.GetFunctionPointerForDelegate函數將System.Delegate轉換爲IntPtr32。否則,你通過某些指針指向某處到受管堆。

因此改變

mydelegate =new CallBackDelegate(CallbackFunction); 
SetCallBackPointer(mydelegate); 

mydelegate =new CallBackDelegate(CallbackFunction); 

SetCallBackPointer(Marshal.GetFunctionPointerForDelegate(delegate)); 

和修復SetCallBackPointer的C#聲明

[DllImport("serialport.dll")] 
private static extern void SetCallBackPointer(IntPtr Delegate);