When performing C# Interop/PInvoke with C++, you sometimes need to send structs from managed memory, to unmanaged memory.
In these cases .NET will perform Marshaling for you on your data. You can customize this marshaling with attributes.
Verify.Marshaling allows you to perform Snapshot Testing on the memory layouts of your structs.
This can be useful in order to compare them to their C++ equivalents, or to lock their layout between versions of a library.
If you're new to Verify, we recommend checking out the Verify getting started wizard.
Install Verify.Marshaling with NuGet:
Install-Package YellowDogMan.Verify.Marshaling
Given a struct:
[StructLayout(LayoutKind.Sequential)]
public struct SimpleStruct
{
[MarshalAs(UnmanagedType.I4)]
public int Test;
[MarshalAs(UnmanagedType.R4)]
public float TestF;
}
You can verify its layout with:
[TestMethod]
public async Task BasicTest()
{
await VerifyMemoryLayout(typeof(SimpleStruct));
}
Which should produce an output like:
{
FieldName: SimpleStruct,
Size: 8,
Nested: [
{
FieldName: Test,
Size: 4,
Type: Int32
},
{
FieldName: TestF,
Size: 4,
Offset: 4,
Type: Single
}
],
Type: struct
}
That can be saved as a part of your Snapshot collection, in the same way as Verify
We make heavy use of this in Compressonator.NET to Verify communication with the Native Library.
If you have any suggestions or improvements, please feel free to open an issue or submit a pull request. We're new to making extensions for Verify and would love to improve things.
Projects like StructLayout and even Visual Studio. Generate visual diagrams of a struct's layout.
Tooling to generate these for C# may be handy as an alternative method to verify the layout.
There are a number of tools for C++ that can examine memory layouts.
Matching these formats, may allow for automated tests that produce C++ sourced CLang dumps, that we can then compare with Verify.Marshaling snapshots. We could also convert between them.