2016-12-09 10 views
-3

C++のDLLからC#へのP/Invokeのために、私はいくつかのDLLを開発しました。しかし、私はハードリアルタイム環境で働き、P/Invokeはあまりにも遅すぎて特定の操作を実行できませんでした。C++/C#interopでのメモリマッピングとP/Invokeのパフォーマンス

は、だから私はP /呼び出すために、私のテストの間に(おそらく)より高速の代替として、メモリマッピングに出くわした、物事のC++側は、あまりにもみすぼらしい見ていない:

#include "stdafx.h" 

#define BUF_SIZE 256 
TCHAR szName[] = TEXT("MyFileMappingObject"); 
char* pcTest = "Message from C++"; 

int _tmain() 
{ 
    HANDLE hMapFile; 
    LPCTSTR pBuf; 

    hMapFile = CreateFileMapping(
       INVALID_HANDLE_VALUE, 
       NULL, 
       PAGE_READWRITE, 
       0, 
       BUF_SIZE, 
       szName); 

    if (hMapFile == NULL) { 
     _tprintf(TEXT("Could not create file mapping object (%d).\n"), GetLastError()); 
     return 1; 
    } 

    pBuf = (LPTSTR)MapViewOfFile(
       hMapFile, 
       FILE_MAP_ALL_ACCESS, 
       0, 
       0, 
       BUF_SIZE); 

    if (pBuf == NULL) { 
     _tprintf(TEXT("Could not map view of file (%d).\n"), GetLastError()); 
     CloseHandle(hMapFile); 
     return 1; 
    } 

    CopyMemory((PVOID)pBuf, pcTest, (strlen(pcTest) * sizeof(char*))); 

    std::cin.get(); 

    UnmapViewOfFile(pBuf); 
    CloseHandle(hMapFile); 

    return 0; 
} 

私はからコードを適応ここに:

https://msdn.microsoft.com/en-us/library/windows/desktop/aa366551(v=vs.85).aspx

そしてここでは、C#側である:

static void Main(string[] args) 
    { 
     MemoryMappedFile pagedMemoryMap = MemoryMappedFile.OpenExisting("MyFileMappingObject", MemoryMappedFileRights.FullControl); 

     using (MemoryMappedViewAccessor fileMap = pagedMemoryMap.CreateViewAccessor()) 
     { 
      var array = new byte[256]; 
      fileMap.ReadArray(0, array, 0, 16); //Take notice on this line 
      var text = Encoding.ASCII.GetString(array); 
      Console.WriteLine(text); 
     } 

     Console.ReadKey(); 
    } 

これは意図したとおりに動作しますが、ここに問題があります。ReadArrayメソッドのバイト配列長の固定サイズ。実際のアプリケーションの実際の文字列の長さを別の共有に書き込んで文字列値を読み込む必要があると思いますが、それはあまりにも面倒です。実際のアプリケーションでC++から実際に読み込んだものが構造体の配列(文字列のみを含む)であることを考慮すると、パフォーマンスマッピングでメモリマッピングの利得を得ることができますか?私は意図した結果が得られない可能性のある代替コードを使用して安定したコードを作成する意図はありません(遅いですが)。よりよい選択肢がありますか?

+1

C#は、ハードリアルタイム環境には適していません。ガベージコレクタはあなたのタイミングを逃します。事実、Windowsはハードリアルタイム環境には適していません。ページングや割り込み処理がタイミングを逃してしまうからです。ソフトリアルタイム/ニアリアルタイムは別の話です。 –

+0

もちろん、私たちは1対1の比率を持つつもりはありません。 C#の部分は視覚化のためのものであり、値が高レベルでいくつかの更新が欠落しても問題にならないように、絶え間なく迅速に更新されます。しかし、ソフトリアルタイムエミュレータを使ってすべてを動かすことはうまくいきますが、実際のハードウェアに接続すれば、実際にはうまくいきません。 – makoshichi

答えて

2

メモリマップファイルは、プロセス間でデータを共有するのに適しています。同じメモリ空間内のモジュール間で共有することは無意味です。

通常の方法でデータ構造を参照クラスの型として定義し、ピンで固定します。現在、C++は通常のポインタアクセスを使用して直接データ構造にアクセスできます。

カウントされた文字列は、メモリマップされたファイルと同様にピン配列でも動作しますが、カーネルコールを設定する必要はありません。

+0

私はオブジェクトを固定することについてあなたの提案が好きです。私は月曜日にそれを試し、結果を報告します – makoshichi