The most common problem is that all examples that I've found, copies arrays, or fills them up. But no examples of getting a pointer back into an array, without giving the startindex and count of the elements.
I made it possible to convert an array to pointer and visa versa, without those boundaries. You will have to use this class however to convert to and from the pointers. Because I add a 'delimiter' to the end of the data in the pointer.
I hope some of you can use the snippet(s) below. If so, let me know ;)
Regards
1: public static unsafe class Pointers
2: {
3: #region To Pointer
4:
5: /// <summary>
6: /// Converts an array to a pointer.
7: /// Ex. int[] to int*
8: /// </summary>
9: /// <param name="array">Array to convert.</param>
10: /// <returns>Pointer to array</returns>
11: public static int* ConvertArrayToPointer(int[] array)
12: {
13: fixed (int* pArray = array)
14: {
15: int* reference = pArray;
16: *(reference + array.Length) = int.MinValue;
17: return pArray;
18: }
19: }
20:
21: /// <summary>
22: /// Converts an array to a pointer.
23: /// Ex. uint[] to uint*
24: /// </summary>
25: /// <param name="array">Array to convert.</param>
26: /// <returns>Pointer to array</returns>
27: public static uint* ConvertArrayToPointer(uint[] array)
28: {
29: fixed (uint* pArray = array)
30: {
31: uint* reference = pArray;
32: *(reference + array.Length) = uint.MaxValue;
33: return pArray;
34: }
35: }
36:
37: /// <summary>
38: /// Converts an array to a pointer.
39: /// Ex. char[] to char*
40: /// </summary>
41: /// <param name="array">Array to convert.</param>
42: /// <returns>Pointer to array</returns>
43: public static char* ConvertArrayToPointer(char[] array)
44: {
45: fixed (char* pArray = array)
46: {
47: char* reference = pArray;
48: *(reference + array.Length) = char.MinValue;
49: return pArray;
50: }
51: }
52:
53: #endregion
54:
55: #region FromPointer
56:
57: /// <summary>
58: /// Converts a pointer to an array to a managed array.
59: /// Ex. int* to int[]
60: /// </summary>
61: /// <param name="array">Pointer to an array to convert</param>
62: /// <param name="startIndex">StartIndex from where to convert</param>
63: /// <param name="count">Number of elements to include in result-array</param>
64: /// <returns>Requested array of elements.</returns>
65: public static int[] ConvertPointerToArray(int* array, int startIndex, int count)
66: {
67: int[] data = new int[count -startIndex];
68:
69: for (int i = startIndex; i < count; i++)
70: {
71: int tempVal = *(array + i);
72: data[i] = tempVal;
73: }
74: return data;
75: }
76:
77: /// <summary>
78: /// Converts a pointer to an array to an array.
79: /// This array has an delimitor at the end to know when to stop converting.
80: /// </summary>
81: /// <param name="array">Pointer to an array</param>
82: /// <returns>Requested array</returns>
83: public static int[] ConvertPointerToArray(int* array)
84: {
85: List<int> data = new List<int>();
86:
87: int index = 0;
88: int tempVal = *(array + index++);
89: data.Add(tempVal);
90:
91: while (tempVal != int.MinValue)
92: {
93: tempVal = *(array + index++);
94: if(tempVal != int.MinValue)
95: data.Add(tempVal);
96: }
97:
98: return data.ToArray();
99: }
100:
101: /// <summary>
102: /// Converts a pointer to an array to a managed array.
103: /// Ex. char* to char[]
104: /// </summary>
105: /// <param name="array">Pointer to an array to convert</param>
106: /// <param name="startIndex">StartIndex from where to convert</param>
107: /// <param name="count">Number of elements to include in result-array</param>
108: /// <returns>Requested array of elements.</returns>
109: public static char[] ConvertPointerToArray(char* array, int startIndex, int count)
110: {
111: char[] data = new char[count - startIndex];
112:
113: for (int i = startIndex; i < count; i++)
114: {
115: char tempVal = *(array + i);
116: data[i] = tempVal;
117: }
118: return data;
119: }
120:
121: /// <summary>
122: /// Converts a pointer to an array to an array.
123: /// This array has an delimitor at the end to know when to stop converting.
124: /// </summary>
125: /// <param name="array">Pointer to an array</param>
126: /// <returns>Requested array</returns>
127: public static char[] ConvertPointerToArray(char* array)
128: {
129: List<char> data = new List<char>();
130:
131: int index = 0;
132: char tempVal = *(array + index++);
133: data.Add(tempVal);
134:
135: while (tempVal != char.MinValue)
136: {
137: tempVal = *(array + index++);
138: if (tempVal != char.MinValue)
139: data.Add(tempVal);
140: }
141:
142: return data.ToArray();
143: }
144:
145: /// <summary>
146: /// Converts a pointer to an array to a managed array.
147: /// Ex. uint* to uint[]
148: /// </summary>
149: /// <param name="array">Pointer to an array to convert</param>
150: /// <param name="startIndex">StartIndex from where to convert</param>
151: /// <param name="count">Number of elements to include in result-array</param>
152: /// <returns>Requested array of elements.</returns>
153: public static uint[] ConvertPointerToArray(uint* array, int startIndex, int count)
154: {
155: uint[] data = new uint[count - startIndex];
156:
157: for (int i = startIndex; i < count; i++)
158: {
159: uint tempVal = *(array + i);
160: data[i] = tempVal;
161: }
162: return data;
163: }
164:
165: /// <summary>
166: /// Converts a pointer to an array to an array.
167: /// This array has an delimitor at the end to know when to stop converting.
168: /// </summary>
169: /// <param name="array">Pointer to an array</param>
170: /// <returns>Requested array</returns>
171: public static uint[] ConvertPointerToArray(uint* array)
172: {
173: List<uint> data = new List<uint>();
174:
175: int index = 0;
176: uint tempVal = *(array + index++);
177: data.Add(tempVal);
178:
179: while (tempVal != uint.MaxValue)
180: {
181: tempVal = *(array + index++);
182: if (tempVal != uint.MaxValue)
183: data.Add(tempVal);
184: }
185:
186: return data.ToArray();
187: }
188:
189: #endregion
190:
191: #region Internal Pointers
192:
193: /// <summary>
194: /// Converts a structure to a IntPtr
195: /// </summary>
196: /// <typeparam name="T">Type of structure</typeparam>
197: /// <param name="value">Struct to convert</param>
198: /// <returns>IntPtr of the struct</returns>
199: public static IntPtr ToIntPtr<T>(T value)
200: where T : struct
201: {
202: IntPtr pointer = Marshal.AllocHGlobal(Marshal.SizeOf(value));
203: Marshal.StructureToPtr(value, pointer, true);
204: return pointer;
205: }
206:
207: /// <summary>
208: /// Converts an IntPtr to a struct
209: /// </summary>
210: /// <typeparam name="T">Type of structure</typeparam>
211: /// <param name="pointer">Internal Pointer of structure</param>
212: /// <returns>Requested struct</returns>
213: public static T FromIntPtr<T>(IntPtr pointer, bool destruct)
214: where T : struct
215: {
216: T structure = (T)Marshal.PtrToStructure(pointer, typeof(T));
217: if (destruct)
218: {
219: Marshal.Release(pointer);
220: }
221: return structure;
222: }
223:
224: #endregion
225:
226:
227: public static void DoTest(int[] array)
228: {
229: // Make a pointer of the array
230: int* pointer = Pointers.ConvertArrayToPointer(array);
231: // Make an array of the pointer-data
232: int[] data = Pointers.ConvertPointerToArray(pointer, 0, array.Length);
233: // Same as above, but without bounderies.
234: data = Pointers.ConvertPointerToArray(pointer);
235:
236: // Make us a testing structure
237: TestStruct ts = new TestStruct("This is my teststruct");
238: // Convert the struct to an IntPtr
239: IntPtr ptr = ToIntPtr<TestStruct>(ts);
240: // Convert IntPtr back to a struct.
241: // Don't forget the destruction, for memory leak prevention!
242: TestStruct test = FromIntPtr<TestStruct>(ptr, true);
243: }
244:
245: internal struct TestStruct
246: {
247: private string _msg;
248:
249: public TestStruct(string message)
250: {
251: _msg = message;
252: }
253:
254: public string Msg
255: {
256: get { return _msg; }
257: set { _msg = value; }
258: }
259: }
260: }
1 comment:
Per Microsoft Documentation on "fixed":
After the code in the statement is executed, any pinned variables are unpinned and subject to garbage collection. Therefore, do not point to those variables outside the fixed statement.
So, returned pointer from your routines is un-fixed. Object can be moved in memory...
Post a Comment