DOBON.NET DOBON.NETプログラミング掲示板過去ログ

VB.NETでのメモリマップドファイル(共有メモリ)へのアクセス

環境/言語:[OS : Windows XP Professional / 言語 : Visual Basic .NET]
分類:[.NET]

【解決したい問題】

C++で作成されたアプリケーションとの連携のため、メモリマップドファイル(共有メモリ)によるデータ取得をVB.NETで行おうとしておりますが、どのようにすれば共有メモリにアクセスできるかわからず、お知恵をお借りできますでしょうか。

【解決するために何をしたか】

http://www.athomejp.com/goldfish/api/sharedmemory.asp
こちらを参照し、CreateFileMapping及びMapViewOfFileを利用することとしました。
<DllImport("kernel32.dll")> _
Public Function CreateFileMapping(ByVal hFile As IntPtr, _
 ByVal lpFileMappingAttributes As IntPtr, ByVal flProtect As UInt32, ByVal dwMaximumSizeHigh As UInt32, _
 ByVal dwMaximumSizeLow As UInt32, ByVal lpName As String) As IntPtr
End Function

<DllImport("kernel32.dll")> _
Public Function MapViewOfFile(ByVal hMap As IntPtr, _
 ByVal AccessMode As UInt32, ByVal OffsetHigh As UInt32, ByVal OffsetLow As UInt32, _
 ByVal MapSize As UInt32) As IntPtr
End Function

 上記サイトを参考に、共有メモリの作成、初期化を以下のように行い
Private MemoryMappedFile As IntPtr = &HFFFFFFFF
Private MemorySize As UInt32 = 256
Private ShareName As String = "MyShare"
Dim hFileMap As IntPtr

----

Try
 hFileMap = CreateFileMapping(MemoryMappedFile, Nothing, PageAttribute.PAGE_READWRITE, 0, MemorySize, ShareName)
 If hFileMap = 0 Then
  MsgBox("失敗")
  Return
 End If
Catch ex As Exception
 MsgBox(ex.Message)
 Return
End Try

Dim hMap As IntPtr

Try
 hMap = MapViewOfFile(hFileMap, FileDesiredAccess.FILE_MAP_ALL_ACCESS, 0, 0, 0)
If hMap = 0 Then
 MsgBox("Fail")
 CloseHandle(hFileMap)
 hFileMap = Nothing
 Return
End If
Catch ex As Exception
 MsgBox(ex.Message)
 Return
End Try

ZeroMemory(hMap, MemorySize)
UnmapViewOfFile(hMap)

 エラー等なく、上記処理を行えるところまで確認したのですが、この共有メモリに対しByte()配列を書き込む/読み込む為にはどうすればよいか、で壁に当たってしまいました。

【追加事項】

ReadFile/WriteFile等ではなく、MapViewOfFileで返されるポインタへアクセスすればよいと思うのですが、VB.NETではどうすればよいかわからず、基本的な事だとは思いますが、ご教授願えますでしょうか。
 お願いいたします
> ReadFile/WriteFile等ではなく、MapViewOfFileで返されるポインタへアクセスすればよいと思うのですが、VB.NETではどうすればよいかわからず、基本的な事だとは思いますが、ご教授願えますでしょうか。
>  お願いいたします

そもそも、ファイルマッピングオブジェクトに ReadFile/WriteFileで読み書きしちゃダメですよ。

IntPtr から MemoryStream を作る方法とかあればいいのになぁ。
Marshal.Copy でマネージメモリに持ってきて、そこを読み書きして、また Marshal.Copy でアンマネージメモリに書き戻すといったような処理が必要なのかな。
#メモリマップドファイルは使ったことはありません。
#C++もあまり使ったことありません。的外れでしたらすみません。

> C++で作成されたアプリケーションとの連携のため、メモリマップドファイル(共有メモリ)によるデータ取得をVB.NETで行おうとしておりますが、どのようにすれば共有メモリにアクセスできるかわからず、お知恵をお借りできますでしょうか。

CreateFileMapping、MapViewOfFileといったAPI同様に
他のAPIもC++側で使っているのではないかなと思うのですが、
それと同じようにVB側からもAPIを使えばよいのではないでしょうか?

> ReadFile/WriteFile等ではなく、MapViewOfFileで返されるポインタへアクセスすればよいと思うのですが、

返されるポインタに書き込めばOKなのであれば、たぶん、
Marshal クラス (System.Runtime.InteropServices)の
ReadXXX/WriteXXXなメソッドで読み書きできると思います。
■No19306に返信(よねKENさんの記事)
> CreateFileMapping、MapViewOfFileといったAPI同様に
> 他のAPIもC++側で使っているのではないかなと思うのですが、
> それと同じようにVB側からもAPIを使えばよいのではないでしょうか?

C/C++では特にAPIを使わずに読み書きが可能です。

> 返されるポインタに書き込めばOKなのであれば、たぶん、
> Marshal クラス (System.Runtime.InteropServices)の
> ReadXXX/WriteXXXなメソッドで読み書きできると思います。

おぉ、アンマネージメモリを直接読み書きできたのですね。
というわけで、俺の Marshal.Copy は撤回です。
> IntPtr から MemoryStream を作る方法とかあればいいのになぁ。

.NET 2.0 には UnmanagedMemoryStream が用意されています。
■No19309に返信(Hongliangさんの記事)
>>IntPtr から MemoryStream を作る方法とかあればいいのになぁ。
>
> .NET 2.0 には UnmanagedMemoryStream が用意されています。

なんとー!(゚д゚´;)
ありがとうございます。
■No19310に返信(シャノンさんの記事)
> ■No19309に返信(Hongliangさんの記事)
> >>IntPtr から MemoryStream を作る方法とかあればいいのになぁ。
>>
>>.NET 2.0 には UnmanagedMemoryStream が用意されています。
>
> なんとー!(゚д゚´;)
> ありがとうございます。

あ、これ、VB.NET から使えなさそう…
なんでコンストラクタに Byte* とか取るかなぁ。IntPtr にしてよママン。
ありがとうございます!
 まずはMarshalクラスを利用してみる方法を試してみます。
 
#UnmanagedMemoryStreamについては、Marshalクラスで行った後でVB.NETで利用できないか確認してみます
Byte配列を取得するため、
Dim tBuf(MemorySize - 1) As Byte
Marshal.Copy(lpBuf, tBuf, 0, MemorySize)
UnmapViewOfFile(lpBuf)

とし、受け取れることを確かめられました。
ありがとうございました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板