├── README.md
├── MarshalHelper
├── App.config
├── Properties
│ └── AssemblyInfo.cs
├── MarshalHelper.csproj
├── Program.cs
├── ByteHelper.cs
└── MarshalHelper.cs
└── MarshalHelper.sln
/README.md:
--------------------------------------------------------------------------------
1 | # MarshalHelper
2 | C#内存管理—职场生存的必修课 https://www.cnblogs.com/kiba/p/10971744.html
3 |
--------------------------------------------------------------------------------
/MarshalHelper/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/MarshalHelper/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的一般信息由以下
6 | // 控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle("MarshalHelper")]
9 | [assembly: AssemblyDescription("https://www.cnblogs.com/kiba/")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("MarshalHelper")]
13 | [assembly: AssemblyCopyright("Copyright © 2019")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // 将 ComVisible 设置为 false 会使此程序集中的类型
18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
19 | //请将此类型的 ComVisible 特性设置为 true。
20 | [assembly: ComVisible(false)]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid("f93c4a05-ec2c-499d-bcb7-5aa6a250516d")]
24 |
25 | // 程序集的版本信息由下列四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 生成号
30 | // 修订号
31 | //
32 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
33 | // 方法是按如下所示使用“*”: :
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/MarshalHelper.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.645
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MarshalHelper", "MarshalHelper\MarshalHelper.csproj", "{F93C4A05-EC2C-499D-BCB7-5AA6A250516D}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {F93C4A05-EC2C-499D-BCB7-5AA6A250516D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {F93C4A05-EC2C-499D-BCB7-5AA6A250516D}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {F93C4A05-EC2C-499D-BCB7-5AA6A250516D}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {F93C4A05-EC2C-499D-BCB7-5AA6A250516D}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {78721864-05F6-4AA8-8A56-CAEC0B62D7DB}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/MarshalHelper/MarshalHelper.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {F93C4A05-EC2C-499D-BCB7-5AA6A250516D}
8 | Exe
9 | MarshalHelper
10 | MarshalHelper
11 | v4.6.1
12 | 512
13 | true
14 | true
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 | true
26 |
27 |
28 | AnyCPU
29 | pdbonly
30 | true
31 | bin\Release\
32 | TRACE
33 | prompt
34 | 4
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/MarshalHelper/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace MarshalHelper
8 | {
9 | class Program
10 | {
11 | static void Main(string[] args)
12 | {
13 | PointerUsage();
14 |
15 | IntPtr unsafePI = new IntPtr();
16 | int testint = 518;
17 | unsafePI = MarshalHelper.Int32ToIntPtr(testint);
18 | int UnsaferetNoFree = Unsafe_Int32ToIntPtr_NoFree(unsafePI);
19 | Console.WriteLine("Unsafe_Int32ToIntPtr_Free-取IntPtr的值" + UnsaferetNoFree);
20 | new Task(() =>
21 | {
22 | int unsafeafterNoFree = MarshalHelper.IntPtrToInt32(unsafePI);
23 | Console.WriteLine("Int32ToIntPtr_NoFree-未释放Intptr的线程取值" + unsafeafterNoFree);
24 | }).Start();
25 | Console.ReadKey();
26 |
27 | int retNoFree = Int32ToIntPtr_NoFree();
28 | IntPtr retNoFreeIP = new IntPtr(retNoFree);
29 | int retFree = Int32ToIntPtr_Free();
30 | IntPtr retFreeIP = new IntPtr(retFree);
31 |
32 | new Task(() =>
33 | {
34 | int afterNoFree = MarshalHelper.IntPtrToInt32(retNoFreeIP);
35 | Console.WriteLine("Int32ToIntPtr_NoFree-未释放Intptr的线程取值" + afterNoFree);
36 | int afterFree = MarshalHelper.IntPtrToInt32(retFreeIP);
37 | Console.WriteLine("Int32ToIntPtr_Free-已释放Intptr的线程取值" + afterFree);
38 |
39 | }).Start();
40 |
41 | Console.ReadKey();
42 |
43 | }
44 | #region SafeCode 安全代码
45 | static int Int32ToIntPtr_Free()
46 | {
47 | IntPtr pointerInt = new IntPtr();
48 | int testint = 518;
49 | pointerInt = MarshalHelper.Int32ToIntPtr(testint);
50 | int testintT = MarshalHelper.IntPtrToInt32(pointerInt);
51 | Console.WriteLine("Int32ToIntPtr_Free-取IntPtr的值" + testintT);
52 | MarshalHelper.Free(pointerInt);
53 | int testintT2 = (int)pointerInt;
54 | return testintT2;
55 | }
56 | static int Int32ToIntPtr_NoFree()
57 | {
58 | IntPtr pointerInt = new IntPtr();
59 | int testint = 518;
60 | pointerInt = MarshalHelper.Int32ToIntPtr(testint);
61 | int testintT = MarshalHelper.IntPtrToInt32(pointerInt);
62 | Console.WriteLine("Int32ToIntPtr_NoFree-取IntPtr的值" + testintT);
63 | int testintT2 = (int)pointerInt;
64 | return testintT2;
65 |
66 | }
67 | #endregion
68 |
69 | #region UnsafeCode 不安全代码
70 | static int Unsafe_Int32ToIntPtr_NoFree(IntPtr pointerInt)
71 | {
72 | unsafe
73 | {
74 | int *pi = (int*)pointerInt.ToPointer();
75 | return *pi;
76 | }
77 | }
78 | #endregion
79 |
80 | public static void PointerUsage()
81 | {
82 | string str = "I am Kiba518!";
83 | int strlen = str.Length;
84 | IntPtr sptr = MarshalHelper.StringToIntPtr(str);
85 | unsafe
86 | {
87 | char* src = (char*)sptr.ToPointer();
88 | //Console.WriteLine("地址" + (&src)); //这样写会报错,C#并不支持这样取指针地址
89 | for (int i = 0; i <= strlen; i++)
90 | {
91 | Console.Write(src[i]);
92 | src[i] = '0';
93 | }
94 | Console.WriteLine();
95 | Console.WriteLine("========不安全代码改值=========");
96 | for (int i = 0; i <= strlen; i++)
97 | {
98 | Console.Write(src[i]);
99 | }
100 | }
101 | Console.ReadKey();
102 | }
103 |
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/MarshalHelper/ByteHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices;
6 | using System.Runtime.Serialization;
7 | using System.Runtime.Serialization.Formatters.Binary;
8 | using System.Text;
9 |
10 | namespace Utility.Tool
11 | {
12 | public class ByteHelper
13 | {
14 | ///
15 | /// 将文件转换成byte[]数组
16 | ///
17 | /// 文件路径文件名称
18 | /// byte[]数组
19 | public static byte[] FileToByte(string fileUrl)
20 | {
21 | try
22 | {
23 | using (FileStream fs = new FileStream(fileUrl, FileMode.Open, FileAccess.Read))
24 | {
25 | byte[] byteArray = new byte[fs.Length];
26 | fs.Read(byteArray, 0, byteArray.Length);
27 | return byteArray;
28 | }
29 | }
30 | catch
31 | {
32 | return null;
33 | }
34 | }
35 |
36 | ///
37 | /// 将byte[]数组保存成文件
38 | ///
39 | /// byte[]数组
40 | /// 保存至硬盘的文件路径
41 | ///
42 | public static bool ByteToFile(byte[] byteArray, string fileName)
43 | {
44 | bool result = false;
45 | try
46 | {
47 | using (FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write))
48 | {
49 | fs.Write(byteArray, 0, byteArray.Length);
50 | result = true;
51 | }
52 | }
53 | catch
54 | {
55 | result = false;
56 | }
57 | return result;
58 | }
59 |
60 | public static byte[] IntToByte(int source)
61 | {
62 | byte[] intBuff = BitConverter.GetBytes(source);
63 | return intBuff;
64 | }
65 |
66 | public static byte[] StringToBytebyEncoding(string source)
67 | {
68 | byte[] Stringbyte = Encoding.Default.GetBytes(source);
69 | return Stringbyte;
70 | }
71 | public static string ByteToStringbyEncoding(byte[] source)
72 | {
73 | string str = System.Text.Encoding.Default.GetString(source);
74 | return str;
75 | }
76 | ///
77 | /// 使用方法 ByteHelper.ByteToInt(pByte.Skip(0).Take(4).ToArray());
78 | ///
79 | ///
80 | ///
81 | public static int ByteToInt32(byte[] source)
82 | {
83 | int intBuff = BitConverter.ToInt32(source, 0);
84 | return intBuff;
85 | }
86 |
87 | public static short ByteToInt16(byte[] source)
88 | {
89 | short intBuff = BitConverter.ToInt16(source, 0);
90 | return intBuff;
91 | }
92 | public static bool ByteToBool(byte[] source)
93 | {
94 | bool booBuff = BitConverter.ToBoolean(source, 0);
95 | return booBuff;
96 | }
97 | public static char ByteToChar(byte[] source)
98 | {
99 | char charBuff = BitConverter.ToChar(source, 0);
100 | return charBuff;
101 | }
102 | public static String ByteToString(byte[] source)
103 | {
104 | String strBuff = BitConverter.ToString(source, 0);
105 | return strBuff;
106 | }
107 |
108 | public static byte[] StructToBytes(T obj)
109 | {
110 | int size = Marshal.SizeOf(typeof(T));
111 | IntPtr bufferPtr = Marshal.AllocHGlobal(size);
112 | try
113 | {
114 | Marshal.StructureToPtr(obj, bufferPtr, false);
115 | byte[] bytes = new byte[size];
116 | Marshal.Copy(bufferPtr, bytes, 0, size);
117 | return bytes;
118 | }
119 | catch (Exception ex)
120 | {
121 | throw new Exception("Error in StructToBytes ! " + ex.Message);
122 | }
123 | finally
124 | {
125 | Marshal.FreeHGlobal(bufferPtr);
126 | }
127 | }
128 |
129 |
130 | //将一个结构序列化为字节数组
131 | private IFormatter formatter = new BinaryFormatter();
132 | private ValueType DeserializeByteArrayToInfoObj(byte[] bytes)
133 | {
134 | ValueType vt;
135 | if (bytes == null || bytes.Length == 0)
136 | {
137 | return null;
138 | }
139 |
140 | try
141 | {
142 | MemoryStream stream = new MemoryStream(bytes);
143 | stream.Position = 0;
144 | stream.Seek(0, SeekOrigin.Begin);
145 | vt = (ValueType)formatter.Deserialize(stream);
146 | stream.Close();
147 | return vt;
148 | }
149 | catch (Exception ex)
150 | {
151 | return null;
152 | }
153 | }
154 | //将一个结构序列化为字节数组
155 | private byte[] SerializeInfoObjToByteArray(ValueType infoStruct)
156 | {
157 | if (infoStruct == null)
158 | {
159 | return null;
160 | }
161 |
162 | try
163 | {
164 | MemoryStream stream = new MemoryStream();
165 | formatter.Serialize(stream, infoStruct);
166 |
167 | byte[] bytes = new byte[(int)stream.Length];
168 | stream.Position = 0;
169 | int count = stream.Read(bytes, 0, (int)stream.Length);
170 | stream.Close();
171 | return bytes;
172 | }
173 | catch (Exception ex)
174 | {
175 | return null;
176 | }
177 | }
178 |
179 | }
180 | }
181 |
--------------------------------------------------------------------------------
/MarshalHelper/MarshalHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Runtime.InteropServices;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using Utility.Tool;
8 |
9 | namespace MarshalHelper
10 | {
11 | public class MarshalHelper
12 | {
13 | #region unsafe 不安全代码 IntPtr to byte[]
14 | public static byte[] Unsafe_IntPtrToByte(IntPtr source, Int32 byteLength)
15 | {
16 | unsafe
17 | {
18 | byte[] data = new byte[byteLength];
19 | void* tempData = source.ToPointer();
20 | using (System.IO.UnmanagedMemoryStream tempUMS = new System.IO.UnmanagedMemoryStream((byte*)tempData, byteLength))
21 | {
22 | tempUMS.Read(data, 0, byteLength);
23 | }
24 | return data;
25 | }
26 | }
27 | #endregion
28 |
29 | #region IntPtr to byte[]
30 | public static byte[] IntPtrToByte(IntPtr pointerInt, Int32 byteLength)
31 | {
32 | try
33 | {
34 | byte[] destinationData = new byte[byteLength];
35 | Marshal.Copy(pointerInt, destinationData, 0, byteLength);//将数据从非托管内存指针复制到托管 8 位无符号整数数组。
36 | return destinationData;
37 | }
38 | catch
39 | {
40 | return null;
41 | }
42 | }
43 | ///
44 | /// 将bytelist复制到非托管内存指针IntPtr里
45 | ///
46 | ///
47 | public static IntPtr ByteToIntPtr(byte[] source)
48 | {
49 | try
50 | {
51 | IntPtr destpointer = Marshal.AllocHGlobal(source.Length);
52 | Marshal.Copy(source, 0, destpointer, source.Length);
53 | return destpointer;
54 | }
55 | catch
56 | {
57 | return IntPtr.Zero;
58 | }
59 | }
60 |
61 | #endregion
62 |
63 | #region string to IntPtr / IntPtr to string
64 | ///
65 | /// 使用Marshal提取[句柄/C++指针]指向的值,并转换成String
66 | ///
67 | public static string IntPtrToString(IntPtr pointer, int byteLength = byte.MaxValue)
68 | {
69 | byte[] destinationData = new byte[byteLength];
70 | Marshal.Copy(pointer, destinationData, 0, byteLength);//将数据从非托管内存指针复制到托管 8 位无符号整数数组。
71 | string strData = Encoding.ASCII.GetString(destinationData);
72 | return strData;
73 | }
74 | ///
75 | /// 使用Marshal将String封装成[句柄/C++指针],形成IntPtr
76 | ///
77 | public static IntPtr StringToIntPtr(string source, Encoding type = null)
78 | {
79 | IntPtr destpointer = IntPtr.Zero;
80 | if (type == null)
81 | {
82 | type = Encoding.Default;
83 | }
84 | switch (type.ToString())
85 | {
86 | case "Default":
87 | destpointer = Marshal.StringToHGlobalAnsi(source);
88 | break;
89 | default:
90 | destpointer = Marshal.StringToHGlobalUni(source);
91 | break;
92 |
93 | }
94 | return destpointer;
95 | }
96 | #endregion
97 |
98 | #region Int32 to IntPtr / IntPtr to Int32
99 | public static IntPtr Int32ToIntPtr(Int32 source)
100 | {
101 | IntPtr destpointer = Marshal.AllocHGlobal(4);
102 | byte[] sourceData = ByteHelper.IntToByte(source);
103 | Marshal.Copy(sourceData, 0, destpointer, sourceData.Length);// 将数据从一维托管 8 位无符号整数数组复制到非托管内存指针。
104 | return destpointer;
105 | }
106 | public static int IntPtrToInt32(IntPtr pointerInt, int byteLength = 4)
107 | {
108 | byte[] destinationData = new byte[byteLength];
109 | Marshal.Copy(pointerInt, destinationData, 0, byteLength);//将数据从非托管内存指针复制到托管 8 位无符号整数数组。
110 | int ret = ByteHelper.ByteToInt32(destinationData);
111 | return ret;
112 | }
113 | #endregion
114 |
115 | #region Int16 to IntPtr / IntPtr to Int16
116 | public static IntPtr Int16ToIntPtr(Int16 source)
117 | {
118 | IntPtr destpointer = Marshal.AllocHGlobal(4);
119 | byte[] sourceData = ByteHelper.IntToByte(source);
120 | Marshal.Copy(sourceData, 0, destpointer, sourceData.Length);// 将数据从一维托管 8 位无符号整数数组复制到非托管内存指针。
121 | return destpointer;
122 | }
123 | public static int IntPtrToInt16(IntPtr pointerInt, int byteLength = 2)
124 | {
125 | byte[] destinationData = new byte[byteLength];
126 | Marshal.Copy(pointerInt, destinationData, 0, byteLength);//将数据从非托管内存指针复制到托管 8 位无符号整数数组。
127 | int ret = ByteHelper.ByteToInt32(destinationData);
128 | return ret;
129 | }
130 | #endregion
131 |
132 | #region struct to IntPtr / IntPtr to struct
133 | public static IntPtr StructToIntPtr(object source)
134 | {
135 | Type type = source.GetType();
136 | int size = Marshal.SizeOf(type);
137 | IntPtr destpointer = Marshal.AllocHGlobal(size);
138 | try
139 | {
140 | Marshal.StructureToPtr(source, destpointer, false);
141 | return destpointer;
142 | }
143 | catch (Exception ex)
144 | {
145 | FreeStruct(destpointer, type);
146 | return IntPtr.Zero;
147 | }
148 | }
149 | public static T IntPtrToStruct(IntPtr source)
150 | {
151 | return (T)Marshal.PtrToStructure(source, typeof(T));
152 | }
153 | public static object IntPtrToStruct(IntPtr source, Type type)
154 | {
155 | return Marshal.PtrToStructure(source, type);
156 | }
157 | #endregion
158 |
159 | #region 释放IntPtr
160 | public static void Free(IntPtr pointer)
161 | {
162 | Marshal.FreeHGlobal(pointer);
163 | }
164 | public static void FreeStruct(IntPtr pointer, Type type)
165 | {
166 | Marshal.DestroyStructure(pointer, type);
167 | }
168 | #endregion
169 |
170 | #region 委托 to IntPtr
171 | public static IntPtr GetFunctionPointer(Delegate pointer)
172 | {
173 | IntPtr ret = Marshal.GetFunctionPointerForDelegate(pointer);
174 | return ret;
175 |
176 | }
177 | #endregion
178 |
179 | #region byte to struct
180 | public static StructType BytesToStruct(byte[] bytesBuffer)
181 | {
182 | // 检查长度。
183 | if (bytesBuffer.Length != Marshal.SizeOf(typeof(StructType)))
184 | {
185 | throw new ArgumentException("bytesBuffer参数和structObject参数字节长度不一致。");
186 | }
187 |
188 | IntPtr bufferHandler = Marshal.AllocHGlobal(bytesBuffer.Length);
189 | for (int index = 0; index < bytesBuffer.Length; index++)
190 | {
191 | Marshal.WriteByte(bufferHandler, index, bytesBuffer[index]);
192 | }
193 | StructType structObject = (StructType)Marshal.PtrToStructure(bufferHandler, typeof(StructType));
194 | Marshal.FreeHGlobal(bufferHandler);
195 | return structObject;
196 | }
197 | #endregion
198 |
199 |
200 |
201 | }
202 | }
203 |
--------------------------------------------------------------------------------