1

私はwin32アセンブリでシリアルポートdllを開発しています(MASM32)。複数のイベントをチェックする独自のスレッドがあり、指定されたバッファーしきい値で、コールバック関数を呼び出して管理対象のメインアプリケーションに通知します。これは、引数/戻り値のない単なる呼び出しです。

起動時に、メインアプリケーションは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.

常にDWORDptrpCallBackFunctionを呼び出すとクラッシュします。最初に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を呼び出す場合、そのような問題はありません。私はここで何が間違っているのですか?

どんなヒントも素晴らしいでしょう!

4

1 に答える 1

0

SetCallBackDelegateは、Delegateオブジェクトではなく、IntPtrを使用する必要があります。

System.DelegateをIntPtr32に変換するには、 Marshal.GetFunctionPointerForDelegate関数を使用する必要があります。それ以外の場合は、マネージヒープを指すポインターを渡します。

だから変更します

 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);
于 2012-06-29T15:13:14.730 に答える