2012-06-28 122 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);