diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs index 6da4b4c69fa..91028ff5a6e 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs @@ -263,6 +263,14 @@ namespace Microsoft.Interop } } + public static StatementSyntax DefaultInit(TypePositionInfo info, StubCodeContext context) + { + // Assign out params to default + return AssignmentStatement( + IdentifierName(info.InstanceIdentifier), + LiteralExpression(SyntaxKind.DefaultLiteralExpression, Token(SyntaxKind.DefaultKeyword))); + } + /// /// Get the marshalling direction for a given in a given . /// For example, an out parameter is marshalled in the direction in a stub, diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/VariableDeclarations.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/VariableDeclarations.cs index fd7ea63dac0..2d693334005 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/VariableDeclarations.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/VariableDeclarations.cs @@ -26,7 +26,7 @@ namespace Microsoft.Interop if (info.RefKind == RefKind.Out) { - initializations.Add(MarshallerHelpers.SkipInitOrDefaultInit(info, context)); + initializations.Add(MarshallerHelpers.DefaultInit(info, context)); } // Declare variables for parameters diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/UnmanagedToManagedCustomMarshallingTests.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/UnmanagedToManagedCustomMarshallingTests.cs index 8defdfd8c4e..af89c22e25f 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/UnmanagedToManagedCustomMarshallingTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/UnmanagedToManagedCustomMarshallingTests.cs @@ -7,6 +7,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.InteropServices.Marshalling; using System.Threading; +using Microsoft.Diagnostics.Runtime; using SharedTypes; using Xunit; using static ComInterfaceGenerator.Tests.UnmanagedToManagedCustomMarshallingTests; @@ -156,11 +157,11 @@ namespace ComInterfaceGenerator.Tests try { var values = new int[] { 1, 32, 63, 124, 255 }; - int freeCalls = IntWrapperMarshallerToIntWithFreeCounts.NumCallsToFree; - - NativeExportsNE.UnmanagedToManagedCustomMarshalling.SumAndSetNativeObjectData(wrapper, values, values.Length, out int _); - + int oldValue = startingValue + 100; + NativeExportsNE.UnmanagedToManagedCustomMarshalling.SumAndSetNativeObjectData(wrapper, values, values.Length, out oldValue); + Assert.Equal(values.Sum(), impl.GetData().i); + Assert.Equal(startingValue, oldValue); Assert.Equal(freeCalls, IntWrapperMarshallerToIntWithFreeCounts.NumCallsToFree); } finally @@ -181,11 +182,11 @@ namespace ComInterfaceGenerator.Tests try { var values = new int[] { 1, 32, 63, 124, 255 }; - int freeCalls = IntWrapperMarshallerToIntWithFreeCounts.NumCallsToFree; - - NativeExportsNE.UnmanagedToManagedCustomMarshalling.SumAndSetNativeObjectData(wrapper, ref values, values.Length, out int _); - + int oldValue = startingValue + 100; + NativeExportsNE.UnmanagedToManagedCustomMarshalling.SumAndSetNativeObjectData(wrapper, ref values, values.Length, out oldValue); + Assert.Equal(values.Sum(), impl.GetData().i); + Assert.Equal(startingValue, oldValue); Assert.Equal(freeCalls + values.Length, IntWrapperMarshallerToIntWithFreeCounts.NumCallsToFree); } finally diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/RefParameters.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/RefParameters.cs new file mode 100644 index 00000000000..3e845103eb2 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/RefParameters.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Runtime.InteropServices; +using SharedTypes; +using Xunit; + +namespace LibraryImportGenerator.IntegrationTests +{ + partial class NativeExportsNE + { + public partial class RefParameters + { + [LibraryImport(NativeExportsNE_Binary, EntryPoint = "out_params")] + public static partial int OutParameters(out int values, out IntFields numValues); + } + } + public class RefParameters + { + [Fact] + public void OutParametersAreDefaultInitialized() + { + int myInt = 12; + IntFields myIntFields = new IntFields() { a = 12, b = 12, c = 12 }; + NativeExportsNE.RefParameters.OutParameters(out myInt, out myIntFields); + Debug.Assert(myInt == default); + Debug.Assert(myIntFields.a == default && myIntFields.b == default && myIntFields.c == default); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/RefParameters.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/RefParameters.cs new file mode 100644 index 00000000000..5868826a359 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/RefParameters.cs @@ -0,0 +1,25 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Diagnostics; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using SharedTypes; + +namespace NativeExports +{ + public static unsafe class RefParameters + { + [UnmanagedCallersOnly(EntryPoint = "out_params")] + public static void EnsureOutParamIsDefault(int* ri, [DNNE.C99Type("struct int_fields*")]IntFields* rif) + { + int i = *ri; + Debug.Assert(i == default); + IntFields _if = *rif; + Debug.Assert(_if.a == default && _if.b == default && _if.c == default); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/VirtualMethodTables.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/VirtualMethodTables.cs index a8e6458fb0a..bc3cac9d0a3 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/VirtualMethodTables.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/VirtualMethodTables.cs @@ -198,6 +198,7 @@ namespace NativeExports [DNNE.C99DeclCode("struct INativeObject;")] public static void SumAndSetData([DNNE.C99Type("struct INativeObject*")] NativeObjectInterface* obj, int* values, int numValues, int* oldValue) { + Debug.Assert(*oldValue == default); obj->VTable->sumAndSetData(obj, values, numValues, oldValue); } @@ -205,6 +206,7 @@ namespace NativeExports [DNNE.C99DeclCode("struct INativeObject;")] public static void SumAndSetDataWithRef([DNNE.C99Type("struct INativeObject*")] NativeObjectInterface* obj, int** values, int numValues, int* oldValue) { + Debug.Assert(*oldValue == default); obj->VTable->sumAndSetDataWithRef(obj, values, numValues, oldValue); }