ProjectArcade
64 строки · 2.5 Кб
1using System.Runtime.InteropServices;
2
3namespace DokanNet
4{
5internal static class NativeStructWrapper
6{
7public static NativeStructWrapper<T> Wrap<T>(T obj) where T : class
8{
9return new NativeStructWrapper<T>(obj);
10}
11}
12/// <summary>
13/// This class allocates unmanaged memory for a native structure and initializes
14/// that memory by marshalling a managed object. It gurantees that the managed
15/// object stays alive and the unmanaged memory block is valid for at least the
16/// lifetime of this object and that the unmanaged memory is released when this
17/// object is disposed.
18///
19/// Since this class derives form SafeBuffer there are many instance methods
20/// available to read and modify the unmanaged buffer in a safe way and when
21/// marshalled to native code in for example a P/Invoke call, it gets automatically
22/// translated to the address of the unmanaged memory block. It also uses reference
23/// counting and is guaranteed to stay alive during such calls.
24/// <see cref="SafeBuffer"/>
25/// </summary>
26/// <typeparam name="T">Type of managed object</typeparam>
27internal class NativeStructWrapper<T> : SafeBuffer where T : class
28{
29/// <summary>
30/// Initializes a new instance by allocating unmanaged memory and marshalling
31/// the supplied managed object to that memory.
32/// </summary>
33/// <param name="obj">Managed object to marshal to unmanaged memory</param>
34public NativeStructWrapper(T obj) : base(ownsHandle: true)
35{
36var size = Marshal.SizeOf(obj);
37SetHandle(Marshal.AllocHGlobal(size));
38Initialize((ulong)size);
39Object = obj;
40Marshal.StructureToPtr(obj, handle, false);
41}
42
43/// <summary>
44/// Initializes an empty instance. Used internally by native marshaller and
45/// not intended to be used directly from user code.
46/// </summary>
47internal NativeStructWrapper() : base(ownsHandle: true) { }
48
49/// <summary>
50/// Managed object that was originally marshalled to unmanaged memory.
51/// </summary>
52public T Object { get; private set; }
53
54/// <summary>
55/// Releases unmanaged memory used by this instance.
56/// </summary>
57/// <returns>Always returns true</returns>
58protected override bool ReleaseHandle()
59{
60Marshal.FreeHGlobal(handle);
61return true;
62}
63}
64}
65