c# shared momory #2

메모리 맵을 위해 파일뷰를 생성하는 클래스 입니다.

MemoryMappedFile.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
using System;
using System.Runtime.InteropServices;
 
namespace SMC_Mapper
{
    class MemoryMappedFile : IDisposable
    {
        private IntPtr fileMapping;
        private readonly int size;
        private readonly FileAccess access;
 
        public enum FileAccess : int
        {
            ReadOnly = 2,
            ReadWrite = 4
        }
 
        private MemoryMappedFile(IntPtr fileMapping, int size, FileAccess access)
        {
            this.fileMapping = fileMapping;
            this.size = size;
            this.access = access;
        }
 
        public static MemoryMappedFile CreateFile(string name, FileAccess access, int size)
        {
            if (size < 0)
                throw new ArgumentException("Size must not be negative""size");
 
            IntPtr fileMapping = sharedMemoryController.CreateFileMapping(0xFFFFFFFFu, null, (uint)access, 0, (uint)size, name);
            if (fileMapping == IntPtr.Zero)
                throw new MemoryMappingFailedException();
 
            return new MemoryMappedFile(fileMapping, size, access);
        }
 
        public MemoryMappedFileView CreateView(int offset, int size, MemoryMappedFileView.ViewAccess access)
        {
            if (this.access == FileAccess.ReadOnly && access == MemoryMappedFileView.ViewAccess.ReadWrite)
                throw new ArgumentException("Only read access to views allowed on files without write access""access");
            if (offset < 0)
                throw new ArgumentException("Offset must not be negative""size");
            if (size < 0)
                throw new ArgumentException("Size must not be negative""size");
            IntPtr mappedView = sharedMemoryController.MapViewOfFile(fileMapping, (uint)access, 0, (uint)offset, (uint)size);
            return new MemoryMappedFileView(mappedView, size, access);
        }
 
        #region IDisposable Member
 
        public void Dispose()
        {
            if (fileMapping != IntPtr.Zero)
            {
                if (sharedMemoryController.CloseHandle((uint)fileMapping))
                    fileMapping = IntPtr.Zero;
            }
        }
 
        #endregion
    }
}
 

아래는 실제로 읽고 쓰는 함수들이 저장되어있습니다.

MemoryMappedFileView.cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
using System;
using System.Runtime.InteropServices;
 
namespace SMC_Mapper
{
    class MemoryMappedFileView : IDisposable
    {
        private IntPtr mappedView;
        private readonly int size;
        private readonly ViewAccess access;
 
        public enum ViewAccess : int
        {
            ReadWrite = 2,
            Read = 4,
        }
 
        internal MemoryMappedFileView(IntPtr mappedView, int size, ViewAccess access)
        {
            this.mappedView = mappedView;
            this.size = size;
            this.access = access;
        }
 
        public int Size
        {
            get { return size; }
        }
 
        public void ReadBytes(byte[] data)
        {
            ReadBytes(data, 0);
        }
        public void ReadBytes(byte[] data, int offset)
        {
            for (int i = 0; i < data.Length; i++)
                data[i] = Marshal.ReadByte(mappedView, offset + i);
        }
 
        public void WriteBytes(byte[] data)
        {
            WriteBytes(data, 0);
        }
        public void WriteBytes(byte[] data, int offset)
        {
            for (int i = 0; i < data.Length; i++)
                Marshal.WriteByte(mappedView, offset + i, data[i]);
        }
 
        #region Additional Accessors
        public byte ReadByte(int offset)
        {
            return Marshal.ReadByte(mappedView, offset);
        }
        public void WriteByte(byte data, int offset)
        {
            Marshal.WriteByte(mappedView, offset, data);
        }
 
        public short ReadInt16(int offset)
        {
            return Marshal.ReadInt16(mappedView, offset);
        }
        public void WriteInt16(short data, int offset)
        {
            Marshal.WriteInt16(mappedView, offset, data);
        }
 
        public int ReadInt32(int offset)
        {
            return Marshal.ReadInt32(mappedView, offset);
        }
        public void WriteInt32(int data, int offset)
        {
            Marshal.WriteInt32(mappedView, offset, data);
        }
 
        public long ReadInt64(int offset)
        {
            return Marshal.ReadInt64(mappedView, offset);
        }
        public void WriteInt64(long data, int offset)
        {
            Marshal.WriteInt64(mappedView, offset, data);
        }
 
        public object ReadStructure(Type structureType)
        {
            return Marshal.PtrToStructure(mappedView, structureType);
        }
        public void WriteStructure(object data)
        {
            Marshal.StructureToPtr(data, mappedView, true);
        }
 
        public object ReadDeserialize()
        {
            return ReadDeserialize(0, size);
        }
        public object ReadDeserialize(int offset)
        {
            return ReadDeserialize(offset, size - offset);
        }
        public object ReadDeserialize(int offset, int length)
        {
            byte[] binaryData = new byte[length];
            ReadBytes(binaryData, offset);
            System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter
                = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
            System.IO.MemoryStream ms = new System.IO.MemoryStream(binaryData, 0, length, truetrue);
            object data = formatter.Deserialize(ms);
            ms.Close();
            return data;
        }
 
        /// <summary>
        /// Serializes the data and writes it to the file.
        /// </summary>
        /// <param name="data">The data to serialize.</param>
        public void WriteSerialize(object data)
        {
            WriteSerialize(data, 0, size);
        }
        /// <summary>
        /// Serializes the data and writes it to the file.
        /// </summary>
        /// <param name="data">The data to serialize.</param>
        /// <param name="offset">The position in the file to start.</param>
        public void WriteSerialize(object data, int offset)
        {
            WriteSerialize(data, 0, size - offset);
        }
        /// <summary>
        /// Serializes the data and writes it to the file.
        /// </summary>
        /// <param name="data">The data to serialize.</param>
        /// <param name="offset">The position in the file to start.</param>
        /// <param name="length">The buffer size in bytes.</param>
        public void WriteSerialize(object data, int offset, int length)
        {
            System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter
                = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
            byte[] binaryData = new byte[length];
            System.IO.MemoryStream ms = new System.IO.MemoryStream(binaryData, 0, length, truetrue);
            formatter.Serialize(ms, data);
            ms.Flush();
            ms.Close();
            WriteBytes(binaryData, offset);
        }
        #endregion
 
        #region IDisposable Member
 
        public void Dispose()
        {
            if (mappedView != IntPtr.Zero)
            {
                if (sharedMemoryController.UnmapViewOfFile(mappedView))
                    mappedView = IntPtr.Zero;
            }
        }
 
        #endregion
    }
}
 


아래는 예외처리 클래스인데.. 특별하게 구현하지는 않았네요..

MemoryMappingFailedException.cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
using System;
 
 
namespace SMC_Mapper
{
    [Serializable]
    class MemoryMappingFailedException : Exception
    {        
        public MemoryMappingFailedException() : base()
        {
        }
    }
}
 


위의 클래스들로 DLL을 하나 만들고 참조해서 사용합니다.

Mapper m_Mapper = new Mapper();
m_Mapper.m_MapDic[메모리맵이름].Write(....);
m_Mapper.m_MapDic[메모리맵이름].Read(....);

하면 간단하게 읽고 쓰기가 가능합니다.

저같이 여러개를 여는것이 아니라면 Mapper라는 클래스가 따로 필요는 없고

file = MemoryMappedFile.CreateFile(mapName, MemoryMappedFile.FileAccess.ReadWrite, size);
view = file.CreateView(0, size, MemoryMappedFileView.ViewAccess.ReadWrite);
 
요 부분만 가지고 있으면 되겠지요..

댓글

이 블로그의 인기 게시물

c# GDI+ 꺼져!! BufferedGraphics

c# 에서 C++ dll 사용하기

c# string 에서 mfc의 LPCTSTR간의 변환