From 03d5468e2acbfedb59466ea95fdcc1c35244ce7c Mon Sep 17 00:00:00 2001 From: Ophura <8chan.com@gmail.com> Date: Mon, 29 Sep 2025 20:45:47 +0200 Subject: [PATCH 1/2] fixed a compile-time error in type-marshalling.md this change adds the `out` keyword to fix such compile-time error as well as inlines the variable declaration for simplicity and renames the variable from `st` to `systemTime` for both clarity and consistency. --- docs/standard/native-interop/type-marshalling.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/standard/native-interop/type-marshalling.md b/docs/standard/native-interop/type-marshalling.md index 4bce686fbf5da..b02506025989f 100644 --- a/docs/standard/native-interop/type-marshalling.md +++ b/docs/standard/native-interop/type-marshalling.md @@ -115,11 +115,10 @@ struct SystemTime public ushort Millisecond; } -public static void Main(string[] args) +public static void Main() { - SystemTime st = new SystemTime(); - GetSystemTime(st); - Console.WriteLine(st.Year); + GetSystemTime(out SystemTime systemTime); + Console.WriteLine(systemTime.Year); } ``` From f190656f5eae11dc5c3c706ad60f2bbe1037eb09 Mon Sep 17 00:00:00 2001 From: Ophura <8chan.com@gmail.com> Date: Mon, 29 Sep 2025 21:33:49 +0200 Subject: [PATCH 2/2] further improved a code block in `type-marshalling.md` this change makes the code block ready-to-run for ease of use with copying. --- .../native-interop/type-marshalling.md | 42 ++++++++++--------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/docs/standard/native-interop/type-marshalling.md b/docs/standard/native-interop/type-marshalling.md index b02506025989f..f05e60ffac31c 100644 --- a/docs/standard/native-interop/type-marshalling.md +++ b/docs/standard/native-interop/type-marshalling.md @@ -99,30 +99,34 @@ When you are calling methods on COM objects in .NET, the .NET runtime changes th Another aspect of type marshalling is how to pass in a struct to an unmanaged method. For instance, some of the unmanaged methods require a struct as a parameter. In these cases, you need to create a corresponding struct or a class in managed part of the world to use it as a parameter. However, just defining the class isn't enough, you also need to instruct the marshaller how to map fields in the class to the unmanaged struct. Here the `StructLayout` attribute becomes useful. ```csharp -[LibraryImport("kernel32.dll")] -static partial void GetSystemTime(out SystemTime systemTime); +using System; +using System.Runtime.InteropServices; -[StructLayout(LayoutKind.Sequential)] -struct SystemTime -{ - public ushort Year; - public ushort Month; - public ushort DayOfWeek; - public ushort Day; - public ushort Hour; - public ushort Minute; - public ushort Second; - public ushort Millisecond; -} +Win32Interop.GetSystemTime(out Win32Interop.SystemTime systemTime); + +Console.WriteLine(systemTime.Year); -public static void Main() +internal static partial class Win32Interop { - GetSystemTime(out SystemTime systemTime); - Console.WriteLine(systemTime.Year); + [LibraryImport("kernel32.dll")] + internal static partial void GetSystemTime(out SystemTime systemTime); + + [StructLayout(LayoutKind.Sequential)] + internal ref struct SystemTime + { + public ushort Year; + public ushort Month; + public ushort DayOfWeek; + public ushort Day; + public ushort Hour; + public ushort Minute; + public ushort Second; + public ushort Millisecond; + } } ``` -The previous code shows a simple example of calling into `GetSystemTime()` function. The interesting bit is on line 4. The attribute specifies that the fields of the class should be mapped sequentially to the struct on the other (unmanaged) side. This means that the naming of the fields isn't important, only their order is important, as it needs to correspond to the unmanaged struct, shown in the following example: +The previous code shows a simple example of calling into `GetSystemTime()` function. The interesting bit is on line 13. The attribute specifies that the fields of the class should be mapped sequentially to the struct on the other (unmanaged) side. This means that the naming of the fields isn't important, only their order is important, as it needs to correspond to the unmanaged struct, shown in the following example: ```c typedef struct _SYSTEMTIME { @@ -134,7 +138,7 @@ typedef struct _SYSTEMTIME { WORD wMinute; WORD wSecond; WORD wMilliseconds; -} SYSTEMTIME, *PSYSTEMTIME; +} SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME; ``` Sometimes the default marshalling for your structure doesn't do what you need. The [Customizing structure marshalling](customize-struct-marshalling.md) article teaches you how to customize how your structure is marshalled.