forked from JMS-1/DVB.NET---VCR.NET
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathCOMArray.cs
More file actions
150 lines (131 loc) · 4.16 KB
/
COMArray.cs
File metadata and controls
150 lines (131 loc) · 4.16 KB
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
using System;
using System.Runtime.InteropServices;
namespace JMS.DVB.DeviceAccess
{
/// <summary>
/// Verwaltet einen Speicherbereich für eine Enumeration von COM Schnittstellen.
/// </summary>
public class COMArray : IDisposable
{
/// <summary>
/// Referenz auf das Feld der Schnittstellen.
/// </summary>
private IntPtr[] m_Array;
/// <summary>
/// Fixierung des Feldes im Speicher.
/// </summary>
private GCHandle m_Handle;
/// <summary>
/// Gesetzt, wenn eine Freigabe bei <see cref="Dispose"/> erforderlich ist.
/// </summary>
private bool m_MustRelease;
/// <summary>
/// Erzeugt ein neues Feld.
/// </summary>
/// <param name="size">Die Anzahl der Elemente in dem Feld.</param>
public COMArray( int size )
: this( size, true )
{
}
/// <summary>
/// Erzeugt ein neues Feld.
/// </summary>
/// <param name="size">Die Anzahl der Elemente in dem Feld.</param>
/// <param name="mustRelease">Gesetzt, wenn der Speicher des Feldes von dieser Instanz verwaltet wird.</param>
public COMArray( int size, bool mustRelease )
{
// Remember
m_MustRelease = mustRelease;
// Allocate
m_Array = new IntPtr[size];
// Lock
m_Handle = GCHandle.Alloc( m_Array, GCHandleType.Pinned );
}
/// <summary>
/// Meldet die Speicheradresse des Feldes.
/// </summary>
public IntPtr Address
{
get
{
// Report
return m_Handle.AddrOfPinnedObject();
}
}
/// <summary>
/// Ermittelt über die COM Schnittstelle eines Feldelementes eine .NET Schnittstelle.
/// </summary>
/// <param name="index">Die 0-basierte laufende Nummer des Elementes.</param>
/// <returns>Das zugehörige .NET Objekt.</returns>
public object GetObject( int index )
{
// Load - will add reference count
return Marshal.GetObjectForIUnknown( m_Array[index] );
}
/// <summary>
/// Ermittelt über die COM Schnittstelle eines Feldelementes eine .NET Schnittstelle.
/// </summary>
/// <typeparam name="T">Die gewünschte Art der .NET Schnittstelle.</typeparam>
/// <param name="index">Die 0-basierte laufende Nummer des Elementes.</param>
/// <returns>Das zugehörige .NET Objekt.</returns>
public T GetObject<T>( int index )
{
// Load
var instance = GetObject( index );
try
{
// Change type
return (T) instance;
}
catch
{
// Cleanup
BDAEnvironment.Release( ref instance );
// Forward
throw;
}
}
/// <summary>
/// Meldet eine COM Schnittstelle im Feld.
/// </summary>
/// <param name="index">Die 0-basierte laufende Nummer eines Feldelementes.</param>
public IntPtr this[int index]
{
get
{
// Report
return m_Array[index];
}
}
/// <summary>
/// Meldet die Anzahl der Feldelemente.
/// </summary>
public int Length
{
get
{
// Report
return m_Array.Length;
}
}
#region IDisposable Members
/// <summary>
/// Beendet die Nutzung dieses Feldes endgültig.
/// </summary>
public void Dispose()
{
// Cleanup array
if (m_MustRelease)
if (m_Array != null)
foreach (var comRef in m_Array)
if (comRef != IntPtr.Zero)
Marshal.Release( comRef );
// Forget
m_Array = null;
// Release memory
if (m_Handle.IsAllocated)
m_Handle.Free();
}
#endregion
}
}