2009-06-03 17 views
2

シリアルポートにいくつかの基本的な書き込みを行うcファイルを実行しようとするとエラーが発生します。私は時々転送に時間がかかるので、非同期に実行しようとしています。私の元のバージョンは正常に動作したWriteFile()コマンドと同期して動作していました。私はOVERLAPPEDを初めて使用していて、それについて感謝して入力します。Windowsの非同期シリアルポート通信を

私は取得していますエラーは次のとおりです。

Debug Assertion Failed! 
<path to dbgheap.c> 
Line: 1317 
Expression: _CrtIsValidHeapPointer(pUserData) 

第2の書き込み関数が呼び出されたとき。メインで

:だっ

{ 
     //initialized port (with overlapped), DBC, and timeouts 

     result = write_port(outPortHandle, 128); 
     result = write_port(outPortHandle, 131); 
    } 




static void CALLBACK write_compl(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped) { 
     //write completed. check for errors? if so throw an exception maybe? 
     printf("write completed--and made it to callback function\n"); 
    } 


int write_port(HANDLE hComm,BYTE* lpBuf) { 

    OVERLAPPED osWrite = {0}; 

    // Create this write operation's OVERLAPPED structure's hEvent. 
    osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 
    if (osWrite.hEvent == NULL) 
     // error creating overlapped event handle 
     return 0; 

    // Issue write. 
    if (!WriteFileEx(hComm, &lpBuf, 1, &osWrite, &write_compl)) { 
     if (GetLastError() != ERROR_IO_PENDING) { 
     // WriteFile failed, but isn't delayed. Report error and abort. 
      printf("last error: %ld",GetLastError()); 
      return 0; //failed, return false; 
     } 
     else { 
     // Write is pending. 
     WaitForSingleObjectEx(osWrite.hEvent, 50, TRUE); //50 ms timeout 

     return -1; //pending 
     } 
    } 
    else { 
     return 1; //finished 
    } 
} 

ない完全なコード、申し訳ありません。私は定数ではなくBYTEの配列を使用していました。しかし、System( "pause")は私のデバッグアサーションに失敗したエラーを引き起こしていました。そして、WriteFileEx()が成功したときに、コードを慎重に調べた後、オーバーラップ構造のイベントに対して警告/コールバック関数が呼び出されることはありません。私はこれらの問題を解決しました。

ReadFileEx()関数が呼び出されたときに割り当てられた構造体(BYTEを格納できるように読み込み可能にする)に割り当てられた構造体で、単一のBYTEを処理/参照するだけで助けが必要です。私はオフセットを使用してBYTEストレージにアクセスし、オーバーラップ構造をnullにする方法を知る必要があります。オーバーラップ構造をnullにすることは、ハンドルをINVALID_HANDLE_VALUEに設定するだけで簡単ですか?

+0

バイト配列のポインタとして定数(128,131)を使用しています。ソースを正しくコピーしましたか? – kgiannakakis

答えて

2

は、私はあなたが問題のカップルを持っていると思う

結果= write_port(outPortHandle、128);

はwrite_portの定義にこれを比較し:

int型write_port(HANDLEのhComm、BYTE * lpBuf){

上記の文が一致していません。その後、BYTE * - > "& lpBuf"のアドレスを取って、WriteFileEx関数へのlpBufポインタへのポインタを渡します。これは、あなたが思うことにはなりません。


書き込みが正常にキューに入れられても、50ミリ秒のタイムアウト内に完了しない場合は、これを修正しても潜在的な問題は発生します。

オーバーラップI/Oを使用する場合、I/Oが完了、キャンセル、または関連付けられたデバイスが閉じられるまで、読み取り/書き込みバッファとオーバーラップ構造が有効であることを確認する必要があります。上記のコードでは、WriteFileExの呼び出しでスタックに存在するオーバーラップされた構造体へのポインタを使用します。 WriteFileExが50ミリ秒以内に完了しない場合、保留中のI/Oは存在しないOVERLAPPED構造体への参照を持ち、アクセス違反(または、アプリケーションのどこかで静かにスタックデータが壊れている)になります。

パフォーマンスが大きな問題ではない場合、これらの生涯の問題を処理する標準的な方法は、オーバーライドされた構造体とデータの読み書きが可能なストレージを含むカスタム構造体を使用することです。書き込みをポストするときに構造体を割り当て、I/O完了ルーチンから構造体を割り当て解除する。インクルードされたOVERLAPPED構造体のアドレスをWriteFileExに渡します。完了ルーチン内のOVERLAPPEDアドレスからカスタム構造体へのアドレスを取得するためのoffsetof。

WriteFileExは実際にはhEventメンバIIRCを使用しません。


編集:私は実際にコードをコンパイルしようとしていない

  1. タイプミスやコードと他の問題があるかもしれません:追加のサンプルコードは、注意してください。
  2. これは、データを送信する最も効率的な方法ではありません(送信される各バイトのメモリブロックの割り当て/割り当て解除)。しかし、改善するのは簡単なはずです。
 
    #include <stddef.h> 
    #include <assert.h> 
    #include <windows.h> 

    // ... 
    typedef struct _MYOVERLAPPED 
    { 
     OVERLAPPED ol; 
     BYTE buffer; 
    } MYOVERLAPPED, *LPMYOVERLAPPED; 
    // ... 

    static void CALLBACK write_compl(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped) 
    { 
     if (NULL == lpOverlapped) 
     { 
      assert(!"Should never happen"); 
      return; 
     } 

     LPBYTE pOlAsBytes = (LPBYTE)lpOverlapped; 
     LPBYTE pMyOlAsBytes = pOlAsBytes - offsetof(MYOVERLAPPED, ol); 
     LPMYOVERLAPPED pMyOl = (LPMYOVERLAPPED)pOlAsBytes; 

     if ((ERROR_SUCCESS == dwErrorCode) && 
      (sizeof(BYTE) == dwNumberOfBytesTransfered)) 
     { 
      printf("written %uc\n", pMyOl->buffer); 
     } 
     else 
     { 
      // handle error 
     } 

     free(pMyOl); 
    } 


    int write_port(HANDLE hComm, BYTE byte) { 

     LPMYOVERLAPPED pMyOl = (LPMYOVERLAPPED)malloc(sizeof(MYOVERLAPPED)); 

     ZeroMemory(pMyOl, sizeof(MYOVERLAPPED)); 
     pMyOl->buffer = byte; 

     // Issue write. 
     if (!WriteFileEx(hComm, &pMyOl->buffer, sizeof(BYTE), pMyOl, &write_compl)) { 
      if (GetLastError() != ERROR_IO_PENDING) { 
      // WriteFile failed, but isn't delayed. Report error and abort. 
       free(pMyOl); 
       printf("last error: %ld",GetLastError()); 
       return 0; //failed, return false; 
      } 
      else { 
      return -1; //pending 
      } 
     } 
     else { 
      free(pMyOl); 
      return 1; //finished 
     } 
    } 
+0

オーバーラップ構造内のオフセットを使用して、バッファの結果として割り当てられる単一のBYTEにアクセスする方法について詳しく説明してくださいReadFileEx()コマンドでは、完了関数からBYTEを処理できますか?私は他のデータ構造にアクセスするためにオフセットを使用することにあまり慣れていません。 また、WaitForSingleObjectEx()にINFINITEタイムアウトを設定すると潜在的な問題がありますか? –

+0

上記の編集を参照してください。それが役に立てば幸い。 – rjnilsson

0
result = write_port(outPortHandle, 128); 
    result = write_port(outPortHandle, 131); 

lpBuf引数はバッファではなく、定数へのポインタでなければなりません。

char buffer; 
buffer = 128; 
result = write_port(outPortHandle, &buffer); 
buffer = 131; 
result = write_port(outPortHandle, &buffer); 

あなたが本当にやりたいことは、バッファ長を渡すことです。


あなたは(あなたのコンパイラがコードをコンパイルすることを拒否する好ましくは、このに対して警告または必要があります)ポインタとして整数を渡している:

char buffer[] = { 128, 131 }; 
    result = write_port(outPortHandle, &buffer, sizeof(buffer)); 

int write_port(HANDLE hComm,BYTE* lpBuf, size_t length) { 

    ... 

    // Issue write. 
    if (!WriteFileEx(hComm, &lpBuf, length, &osWrite, &write_compl)) { 
    ... 
+0

最初の文に「be」を追加し、明確にするためにカンマを追加しましたが、128は決して有効なポインタではありません。 –

+0

各書き込みで1バイトを使用しているので、サイズは常に1です。 –