Table of Contents

Install and make a first parse

This lesson reads a six-byte header into C# values. You need basic C# and a stable .NET 10 SDK. You do not need to clone CStructSharp. For JavaScript, use the separate Node.js and browser quick start.

Create an application

Open a terminal in a directory where you keep projects. Run these commands in PowerShell or a Unix shell:

dotnet new console -n BinaryHeader -f net10.0
cd BinaryHeader
dotnet add package CStructSharp

The first command creates an application targeting .NET 10. The second enters its directory. The third downloads the published package and adds it to the project. If dotnet cannot be found, install the SDK and reopen your terminal.

The library also supports .NET 8. For an existing .NET 8 application, run only the package-add command. To try this new project on .NET 8 using the .NET 10 SDK, change the TargetFramework value in BinaryHeader.csproj from net10.0 to net8.0 and install the .NET 8 runtime before running it. The .NET 10 console template does not accept -f net8.0 directly.

Read six bytes

Replace the entire contents of Program.cs with this program:

using CStructSharp;
using CStructSharp.Values;

var layout = new CStruct("struct header { uint16 kind; uint32 length; };");
byte[] bytes = { 0x02, 0x00, 0x06, 0x00, 0x00, 0x00 };
StructValue header = layout.Parse(bytes, "header");

Console.WriteLine($"kind = {header.Get<ushort>("kind")}");
Console.WriteLine($"length = {header.Get<uint>("length")}");

Run it from the application directory:

dotnet run

Expected output:

kind = 2
length = 6

new CStruct(...) prepares the layout. Reuse that object when reading more data with the same format. bytes is the input; header is the resulting StructValue. The string "header" selects the declaration to read; names are case-sensitive, so "Header" is a different name. header.Get<ushort>("kind") reads one member with a checked conversion to the C# type you name. The same object also supports dynamic field syntax (header.kind); Read values and paths explains what that trades away.

Field Offset Width Bytes Value
kind 0 2 bytes 02 00 2
length 2 4 bytes 06 00 00 00 6

The default is packed placement and little-endian byte order. Packed means no gaps between these fields. Little-endian means the least significant byte comes first. The eight-byte pointer default has no effect here because the layout contains no pointers. See binary layout basics for diagrams and explicit constructor options.

Alignment is a placement rule that may leave unused bytes before a field. With alignment enabled for this header, the four-byte length starts at offset 4, leaving padding at offsets 2 and 3; the header then needs eight bytes. Do not enable alignment merely because native C often uses it. Match the actual file format's rule. This six-byte example deliberately uses packed placement.

Try a change

Change 0x02 to 0x03 and run again. Predict which output changes before running it.

Answer: kind becomes 3; length stays 6. Next, remove the final byte. The read fails because the layout requires six bytes. Restore the byte to fix it. Handle errors explains how applications can report such failures.

You can also run this lesson in the explorer.

Continue with the same header

Follow Write, update, and use a C# class. It adds one operation at a time and includes the complete class definition. Use Choose an API when you are ready to compare other input and output choices.

Continue the layout-language tutorial to learn more declarations and byte layouts. When the layout is part of your program rather than of its input, the same six bytes can be read through a class the compiler generates for you: your first generated layout.