-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy path01_ExternalIPC.cs
263 lines (215 loc) · 9.18 KB
/
01_ExternalIPC.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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
/// <summary>
/// Exposes C# functions, providing access through IPC to C++ implementations
///
/// Access hierarchy for external to internal:
/// ExternalIPC.cs -> NativeMethods.cs -> SensorInterops.h/.cpp -> ActualCPPClass.h/.cpp
/// </summary>
namespace InteropsLibrary
{
/// <summary>
/// Class to communicate with C++ <for your application>.
///
/// NOTE: Referenced content of this region from Frame.cs in Realsense project
/// HandleRef variable, Release function, IDisposable region, Marshaler class
/// </summary>
public class ExternalIPC : IDisposable
{
// Function pointers for complex generics
delegate T ActionRefArray1<T, U>(ref U myArray);
delegate T ActionRefArray2<T, U, V>(ref U myArray1, ref V myArray2);
// Handle for IPC
internal HandleRef m_instance;
// Returns whether sensor was properly validated and initialized
private static readonly ExternalIPC instance = new ExternalIPC();
// Note: constructor is 'private'
private ExternalIPC() { }
// Get Singleton instance
public static ExternalIPC GetInstance()
{
return instance;
}
#region IDisposable Support
private bool disposedValue = false; // To detect redundant calls
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// TODO: dispose managed state (managed objects).
}
// TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
// TODO: set large fields to null.
//Release();
disposedValue = true;
}
}
// TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
~ExternalIPC()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(false);
}
// This code added to correctly implement the disposable pattern.
public void Dispose()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(true);
// TODO: uncomment the following line if the finalizer is overridden above.
GC.SuppressFinalize(this);
}
#endregion
// Free sensor handle. Unused, added for completeness
public void Release()
{
m_instance = new HandleRef(this, IntPtr.Zero);
}
#region Dll Setup
/// <summary>
/// Create instance of sensor, store instance reference and check sensor status.
/// Includes debug output of initialisation and boolean for showing openCV windows.
/// </summary>
public void InitIPCHandle()
{
// Check if handle already exists
if (m_instance.Handle != IntPtr.Zero)
return;
// Set reference handle
m_instance = new HandleRef(this, NativeMethods.InitHandle());
}
#endregion
#region Function Examples
/// <summary> ... </summary>
public bool BasicFunction(int myInt)
{
if (!HandleValidated)
return false;
NativeMethods.BasicFunction(m_instance.Handle, myInt);
return true;
}
/// <summary> ... </summary>
public bool SetSimpleStruct(MyStruct myStruct)
{
if (!HandleValidated)
return false;
NativeMethods.SetSimpleStruct(m_instance.Handle, myStruct);
return true;
}
/// <summary> ... </summary>
public bool UpdateSimpleStruct(ref MyStruct myStruct)
{
if (!HandleValidated)
return false;
bool success = false;
IntPtr myPtr = new IntPtr();
try
{
// Allocate unmanaged memory for MyStruct
myPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MyStruct)));
Marshal.StructureToPtr(myStruct, myPtr, false /*Don't erase struct*/);
// Internally updates the calibration settings and color cropping, then recalculates
// the cropped resolutions. Finally returns the updated tracker calibration settings
NativeMethods.UpdateCalibrationSettings(m_instance.Handle, ref myPtr);
// Assign returned data from unmanaged code
myStruct = (MyStruct)Marshal.PtrToStructure(myPtr, typeof(MyStruct));
success = true;
}
finally
{
// Free unmanaged memory
Marshal.FreeHGlobal(myPtr);
}
return success;
}
/// <summary> ... </summary>
public bool SetStructArray(List<MyStruct> myStructList)
{
if (!HandleValidated)
return false;
bool success = false;
IntPtr[] listPtr = new IntPtr[myStructList.Count];
try
{
// 2. Allocate unmanaged memory in a list of pointers per item
for (int i = 0; i < myStructList.Count; i++)
{
listPtr[i] = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MyStruct)));
Marshal.StructureToPtr(myStructList[i], listPtr[i], false /*No need to erase struct*/);
}
// 3. Set color blobs to tracker
NativeMethods.SetStructArray(m_instance.Handle, listPtr, myStructList.Count);
success = true;
}
finally
{
// 4. Free unmanaged memory
for (int i = 0; i < listPtr.Length; i++)
Marshal.FreeHGlobal(listPtr[i]);
}
return success;
}
/// <summary> ... </summary>
public bool GetArrayData(ref List<MyStruct> myStructList)
{
if (!HandleValidated)
return false;
// Initialise variables
MyStruct tempStruct;
int structSizeBlobData = Marshal.SizeOf(typeof(MyStruct));
// Get MyStruct from tracker
NativeMethods.GetArrayData(m_instance.Handle, out IntPtr blobArrayData, out int blobCount);
// Recreate array of MyStruct from unmanaged code
for (int i = 0; i < blobCount; i++)
{
IntPtr data = new IntPtr(blobArrayData.ToInt64() + structSizeBlobData * i);
tempStruct = (MyStruct)Marshal.PtrToStructure(data, typeof(MyStruct));
myStructList.Add(tempStruct);
}
return true;
}
/// <summary> ... </summary>
public bool GetArrayStruct1ArrayData(ref List<MyStruct> myStructList)
{
if (!HandleValidated)
return false;
// Initialize variables and get MyStruct
IntPtr debugOutput = NativeMethods.GetArrayStruct1ArrayData(m_instance.Handle,
out IntPtr myData1Array, out int myData1ArrayCount,
out IntPtr myData1SizesArray, out int myData1SizesArrayCount);
// Clear old data
myStructList.Clear();
// Assign function to function variable to be called during filled of struct
ActionRefArray1<MyStruct, Point_2f[]> myFuncVar = FillMyStructA;
// Have given struct filled with data from C++
FillStructList_1(ref myStructList, myFuncVar,
ref myDataArray, ref myDataArrayCount, ref myDataSizesArray, ref myDataSizesArrayCount);
return true;
}
/// <summary> ... </summary>
public bool GetArrayStruct2ArrayData(ref List<MyStruct> myStructList)
{
if (!HandleValidated)
return false;
// 2. Initialize variables and get MyStruct from tracker
NativeMethods.GetArrayStruct2ArrayData(m_instance.Handle,
out IntPtr myData1Array, out int myData1ArrayCount,
out IntPtr myData1SizesArray, out int myData1SizesArrayCount,
out IntPtr myData2Array, out int myData2ArrayCount,
out IntPtr myData2SizesArray, out int myData2SizesArrayCount,
);
// Clear old data
myStructList.Clear();
// Assign function to function variable to be called during filled of struct
ActionRefArray2<MyStruct, char[], Point_2f[]> myFuncVar = FillMyStructB;
// Have given struct filled with data from C++
FillStructList_2(ref myStructList, myFuncVar,
ref myData1Array, ref myData1ArrayCount, ref myData1SizesArray, ref myData1SizesArrayCount,
ref myData2Array, ref myData2ArrayCount, ref myData2SizesArray, ref myData2SizesArrayCount);
return true;
}
#endregion
}
}