-
Notifications
You must be signed in to change notification settings - Fork 197
Native memory helper classes
Including the namespace Vanara.InteropServices
provides access to memory helper classes and generic classes. These classes wrap the capabilities exposed by the manual memory extensions. Here is how to use those classes:
As there are many ways to allocate memory under the Windows SDK, IMemoryMethods
provides a means of capturing those schemes for reuse in generic classes. Below is a list of schemes already in the project:
If you need to write your own, deriving from Vanara.InteropServices.MemoryMethodsBase
may help you with some of the intuited methods.
When you need native memory and want it to auto-deallocate when it is cleaned up with the garbage collector, there are two main classes: SafeCoTaskMemHandle
and SafeHGlobalHandle
. In Win8 and later, these are interchangeable. Links to all their base classes are below and I'll cover their use in the next section.
Class | Description/Use | NuGet Package |
---|---|---|
Vanara.InteropServices.SafeAllocatedMemoryHandleBase | Abstract base class for all SafeHandle derivatives that encapsulate handling unmanaged memory. This class assumes read-only memory. |
Vanara.Core |
Vanara.InteropServices.SafeAllocatedMemoryHandle | Abstract base class for all SafeHandle derivatives that encapsulate handling unmanaged memory. |
Vanara.Core |
Vanara.InteropServices.SafeMemoryHandle<TMem> | Abstract base class for all SafeAllocatedMemoryHandle derivatives that apply a specific memory handling routine set. |
Vanara.Core |
Vanara.InteropServices.SafeMemoryHandleExt<TMem> | Abstract base class for all SafeAllocatedMemoryHandle derivatives that apply an extended memory handling routine set for structures and sequences. |
Vanara.Core |
Vanara.InteropServices.SafeCoTaskMemHandle | A SafeHandle for memory allocated via COM. |
Vanara.Core |
Vanara.InteropServices.SafeHGlobalHandle | A SafeHandle for memory allocated via LocalAlloc . |
Vanara.Core |
Allocate raw memory and then work with it.
// Allocate 1024 bytes of memory and use the "using" statement to force disposal at the end of scope
// All memory is zeroed by the helper class
using SafeCoTaskMemHandle mem = new(1024);
// Notice that "mem" implicitly converts to IntPtr and "mem.Size" will implicitly convert to int, uint, long and ulong.
ReadFile(hFile, mem, mem.Size, out var read, default);
// Extract an array of points
POINT[] pts = mem.ToArray<POINT>(10);
// Extract a structure offset from the base
RECT rect = mem.ToStructure<RECT>(80);
// Pull an offset zero-terminated string
string str = mem.ToString(-1, 96);
Convert an array of bytes to native memory to act on.
byte[] bytes = new byte[1024];
// Change byte array to contain the contents you desire
using SafeCoTaskMemHandle mem = new(bytes);
// Tweak a few more bytes directly in memory by writing an offset structure
mem.Write(new RECT(100,100,200,200), false, 256);
// Write out the memory
WriteFile(hFile, mem, mem.Size, out var written, default);
While you can use any SafeAllocatedMemoryHandle
derivative to work with structures, SafeCoTaskMemStruct<TStruct>
simplifies it with a couple helper
methods.
// This autosizes to the size of the structure
using SafeCoTaskMemStruct<RECT> pRect = new(); // Init to 0,0,0,0
pRect.Write(4U, pRect.FieldOffset("top")); // Write to 4th offset = 0,4,0,0
ref RECT rr = ref pRect.AsRef(); // Get a ref to the memory
rr.bottom = 8; // Write last value = 0,4,0,8
RECT r = pRect.Value; // Copies the memory to a struct
Console.Write($"{r.left},{r.top},{r.right},{r.bottom}"); // outputs 0,4,0,8
using SafeCoTaskMemStruct<RECT> pRect = new(r); // Init to 0,4,0,8
Three distinct classes are used to interact with strings in memory that align to the Windows definitions. You can also use any SafeAllocatedMemoryHandle
derivative, but then you'll have to explicitly define the character set. All are derived from SafeMemString<TMem>
, which is a SafeMemoryHandle<TMem>
, and supports most of the methods and properties of both System.String
and System.Text.StringBuilder
.
// Create using a string
using SafeLPTSTR text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor " +
"incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation " +
"ullamco laboris nisi ut aliquip ex ea commodo consequat.";
// Append, replace, remove and read/write indexed characters
text.Append(" Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.");
text.Replace(" ad ", "a");
text.Remove(0, 50);
text[12] = 'X';
// Use equality and comparison operators
if (text == "Unknown string value")
return false;
// Express implicitly as an IntPtr or string
WriteFile(hFile, text, text.Length, out _, default);
Console.WriteLine(text);