以MemoryMappedFile的方式,在.Net程式與原生Dll之間通訊

  • 4095
  • 0

摘要:以MemoryMappedFile的方式,在.Net程式與原生Dll之間通訊

用.Net來寫視窗程式是最容易的,但遇到一些需考量效能或者舊的Library只支援VC6又

沒有.Net的Wrapper就需要自己寫Wrapper,藉由P/Invoke的方式做溝通。

MemoryMappedFile則是另一種可行的方式

依我的例子,我例用VS2010寫介面,並控制所有的硬體,將硬體取得的資料存到MemoryMappedFile中。

而計算的部份就交給VC6寫的dll去執行(因為Library舊,只支援到VC6)。

.Net的部份,其部份程式碼如下:

//建立MemoryMappedFile

_Map = MemoryMappedFile.CreateOrOpen("MyMapFile"Convert.ToInt64(nudCapacity.Value * 0x100000)); //0x100000 = 1MB

//寫入資料

nbsp;  }

//用指標的方式,寫入MemoryMap只要約25ms
        using (MemoryMappedViewAccessor mmva = _Map.CreateViewAccessor(0xA00000, 100 * 0x100000))
        {
          //陣列、字串等都是參考型別,不能用在CreateViewAccessor.Wrete<Stuctrue T> 中
          mmva.Write<ScanData3D>(0, ref data);
 
          //寫入第2筆資料
          data.Index = 1;
          data.IndexX = 1;
          mmva.Write<ScanData3D>(nSize, ref data);                           
          //寫入Array資料 
          unsafe
          {
            byte* pByteOriginal = null;
            try
            {
              mmva.SafeMemoryMappedViewHandle.AcquirePointer(ref pByteOriginal);
              double* pDouble = (double*)pByteOriginal;
              for (int i = 0; i < nLen; i++)
                *pDouble++ = HeightData[i];
 
              byte* pByte = (byte*)pDouble;
              for (int i = 0; i < nLen; i++)
                *pByte++ = btDataZ[i];
              for (int i = 0; i < nLen; i++)
                *pByte++ = ConfData[i];
              for (int i = 0; i < nLen; i++)
                *pByte++ = IntensityData[i];
            }
            finally
            {
              if(pByteOriginal != null)
                mmva.SafeMemoryMappedViewHandle.ReleasePointer();
            }
          }
     }

而在VC6的部份

  HANDLE hMapFile;
  hMapFile = OpenFileMapping(
    FILE_MAP_ALL_ACCESS,   // read/write access
    FALSE,                 // do not inherit the name
    "MyMapFile");        // name of mapping object
 
  if (hMapFile == NULL)
  {
    printf(TEXT("Could not open file mapping object (%d).\n"), GetLastError());
    return 1;
  }

  LPVOID mapView = MapViewOfFile(hMapFile, // handle to map object
    FILE_MAP_ALL_ACCESS,  // read/write permission
    0,                   
    0,                   
    0x300000);                  
 
  if (mapView == NULL)
  {
    printf(TEXT("Could not map view of file (%d).\n"), GetLastError());
    CloseHandle(hMapFile);   
    return 1;
  }
 
  ScanData3D* pData = NULL;
  //pData = new ScanData3D();
  //讀出資料
  //memcpy(pData, mapView, sizeof(ScanData3D));
  pData = (ScanData3D*)mapView;
 
  printf("Size of long = %d\n", sizeof(INT64));
  printf("Index = %d\n", pData->Index);
  printf("Width = %d\n", pData->Width);
  printf("Height = %d\n", pData->Height);
  printf("DataBeginPos = %d\n", pData->DataBeginPos);

  pData++; //next data
  printf("Index = %d\n", pData->Index);
  printf("Width = %d\n", pData->Width);
  printf("Height = %d\n", pData->Height);
  printf("DataBeginPos = %d\n", pData->DataBeginPos);
 
  UnmapViewOfFile(mapView);
  CloseHandle(hMapFile);

 

以上程碼式可能有誤,有需要的人請自行測試囉。

============ 以下是簽名檔 ============

一個小小螺絲釘。

第一次建立Blog,希望以後能慢慢充實它。

Howard