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

共有メモリのオープン

  • 題名: 共有メモリのオープン
  • 著者: とし
  • 日時: 2005/11/24 14:52:32
  • ID: 13847
  • この記事の返信元:
    • (なし)
  • この記事への返信:
    • (なし)
  • ツリーを表示
環境/言語:[Windows2000/VB.NET 2003]
分類:[.NET]

共有メモリについて教えてください。

VB.NETで作成した異なるアプリ間で100000の要素をもつ配列を含んだデータを
共有したいのですが、2箇所の問題が解決できません。


<コード(概略)>
    ' 構造体
    '------------------------------
    Public Structure FileMapDataType
        Dim Data0 As Short
        Dim Data1 As Integer
        <VBFixedString(10), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=10)> _
            Public Data2 As String
        ' 本来は、2次元配列で500×200のデータを持ちたいのですが。。。
        <VBFixedArray(100000), MarshalAs(UnmanagedType.ByValArray, SizeConst:=100001)> _
            Public Data3() As Integer
        Dim Data4 As Short
        Dim Data5 As Double
        Dim Data6 As Integer
        Dim Data7 As Integer

        Public Sub Initialize()
            ReDim Data3(100000)
        End Sub
    End Structure

    Private Structure SECURITY_ATTRIBUTES
        Dim nLength As Integer '' 構造体の大きさ
        Dim lpSecurityDescriptor As Integer '' セキュリティ・ディスクリプタへのポインター
        Dim bInheritHandle As Integer '' ハンドルの継承設定
    End Structure


    ' API
    '------------------------------
    Private Declare Auto Function CreateFileMapping Lib "kernel32" Alias "CreateFileMapping" _
        (ByVal hFile As Integer, ByRef lpFileMappigAttributes As SECURITY_ATTRIBUTES, _
         ByVal flProtect As Integer, ByVal dwMaximumSizeHigh As Integer,  _
        ByVal dwMaximumSizeLow As Integer, ByVal lpName As String) As Integer

    Private Declare Auto Function OpenFileMapping Lib "kernel32" Alias "OpenFileMappingA" _
        (ByVal dwDesiredAccess As Integer, ByVal bInheritHandle As Integer, _
        ByVal lpName As String) As Integer

    Private Declare Auto Function MapViewOfFile Lib "kernel32" _
        (ByVal hFileMappingObject As Integer, ByVal dwDesiredAccess As Integer, _
        ByVal dwFileOffsetHigh As Integer, ByVal dwFileOffsetLow As Integer, _
        ByVal dwNumberOfBytesToMap As Integer) As Integer

    Private Declare Auto Function UnmapViewOfFile Lib "kernel32" _
        (ByRef lpBaseAddress As Integer) As Integer

    Private Declare Auto Function FlushViewOfFile Lib "kernel32" _
        (ByVal lpBaseAddress As Integer, ByVal dwNumberOfBytesToFlush As Integer) As Integer

    Private Declare Auto Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
        (ByVal Destination As Integer, ByRef Source As FileMapDataType, ByVal Length As Integer)

    Private Declare Auto Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
        (ByRef Destination As FileMapDataType, ByVal Source As Integer, ByVal Length As Integer)

    Private Declare Auto Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
        (ByVal Destination As Integer, ByRef Source As FileMapDataType2, ByVal Length As Integer)

    Private Declare Auto Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
        (ByRef Destination As FileMapDataType2, ByVal Source As Integer, ByVal Length As Integer)

    Private Declare Auto Function CloseHandle Lib "kernel32" (ByVal hObject As Integer) As Integer


    ' ファイルマップの作成関数内容
    '------------------------------
        Dim SecurityAttribute As SECURITY_ATTRIBUTES
        Dim Ret As Integer
        Dim DummyBuffer As FileMapDataType
        DummyBuffer.Initialize()

        hFileMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, 0, "TestFileMap")
        If (hFileMap = 0) Then '' 新規にファイルマップを生成する。
            '' 構造体を初期化する。
            SecurityAttribute.bInheritHandle = 0 '' ハンドルの継承しない。
            SecurityAttribute.lpSecurityDescriptor = 0 '' セキュリティをセットしない。
            SecurityAttribute.nLength = Len(SecurityAttribute) '' 構造体のサイズを設定

            hFileMap = CreateFileMapping(&HFFFFFFFF, SecurityAttribute, _
                        PAGE_READWRITE, 0, Len(DummyBuffer), "TestFileMap")

            If (hFileMap = 0) Then Exit Function '' ハンドルが取れなければ失敗

            lpFileMap = MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, 0)
            If lpFileMap = 0 Then Exit Function

            '''' 新規作成の場合はデータを初期化する。
            CopyMemory(lpFileMap, DummyBuffer, Len(DummyBuffer))
            Ret = FlushViewOfFile(lpFileMap, Len(DummyBuffer))
            Console.WriteLine("Len:" & Len(DummyBuffer).ToString)
            If Ret = 0 Then Exit Function
        Else
            lpFileMap = MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, 0)
            If lpFileMap = 0 Then Exit Function
        End If


<ご質問1>
CopyMemoryを行った際、以下のエラーが発生します。
 'System.Runtime.InteropServices.MarshalDirectiveException' の
    ハンドルされていない例外が Project1.exe で発生しました。
 追加情報 : 内部的な制限 : 構造体が複雑すぎるか、大きすぎます。

構造体内の配列を100000→16000ぐらいにするとエラーが発生しなくなります。
何かサイズの制限があるのでしょうか?
100000配列のデータを渡すことが出来るのであれば方法を教えてください。


<ご質問2>
配列のサイズを小さくして実行してみると、共有メモリは作成されているのですが、
再度、同じ関数を呼ぶと、OpenFileMappingで0が返ってきます。
また、LastDllErrorは2が返ってきます。
記述方法が間違っているのでしょうか?
既存のファイルマップのハンドルを取得する方法を教えてください。


ご教示よろしくお願いいたします。

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