2012-06-28 3 views
1

Win32 어셈블리 (MASM32)에서 직렬 포트 dll을 개발 중입니다. 자체 스레드가 여러 이벤트를 검사하고 지정된 버퍼 임계 값에서 콜백 함수를 호출하여 관리되는 주 응용 프로그램에 알립니다. 인수/반환 값이없는 호출입니다. 시작시관리되지 않는 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

에 SetCallBackPointer의 C#을 선언 문제를 해결 pCallBackFunction하지 않습니다 덮어 쓰기) 호출 규칙 (OpenPort에는 많은 매개 변수와 반환 값이 있음)을 확인 했습니까? –

+0

그런데 ... + 1 이유를 설명 할 수없는 경우에도 어셈블리로 작성하고 있기 때문에! –

+0

OpenPort는 dword ...라는 호출을 제공 할 때 잘 동작합니다. pCallBackFunction을 덮어 쓰지 않도록 추가 기능을 추가 할 것입니다. 어셈블리를 작성하는 중 실제 이유는 없습니다. 감사. – JustGreg

답변

0

SetCallBackDelegate는 Delegate 개체가 아닌 IntPtr을 사용해야합니다.

Marshal.GetFunctionPointerForDelegate 함수를 사용하여 System.Delegate를 IntPtr32로 변환해야합니다. 그렇지 않으면 일부 포인터가 어딘가에을 가리키고 관리되는 힙을 전달 중입니다.

는 그래서

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

mydelegate =new CallBackDelegate(CallbackFunction); 

SetCallBackPointer(Marshal.GetFunctionPointerForDelegate(delegate)); 

을 변경하고 있는지 경우 (다른 모든 올바른

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