From ebe6b8a4154d0c8f18ce4f66ca1c9a3a28c35680 Mon Sep 17 00:00:00 2001 From: Salvage <29021710+Saalvage@users.noreply.github.com> Date: Wed, 18 Oct 2023 04:47:13 +0200 Subject: [PATCH] Fix value type out parameters --- src/Generator/Generators/CSharp/CSharpMarshal.cs | 11 +++++++---- src/Generator/Generators/CSharp/CSharpSources.cs | 2 +- tests/dotnet/CSharp/CSharp.Tests.cs | 7 +++++++ tests/dotnet/CSharp/CSharp.cpp | 5 +++++ tests/dotnet/CSharp/CSharp.h | 7 +++++++ 5 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/Generator/Generators/CSharp/CSharpMarshal.cs b/src/Generator/Generators/CSharp/CSharpMarshal.cs index dedd8a9b..df793b56 100644 --- a/src/Generator/Generators/CSharp/CSharpMarshal.cs +++ b/src/Generator/Generators/CSharp/CSharpMarshal.cs @@ -634,17 +634,20 @@ namespace CppSharp.Generators.CSharp { if (Context.Parameter.Usage == ParameterUsage.Out) { - var qualifiedIdentifier = (@class.OriginalClass ?? @class).Visit(typePrinter); - Context.Before.WriteLine("var {0} = new {1}.{2}();", - arg, qualifiedIdentifier, Helpers.InternalStruct); + Context.Before.WriteLine("fixed ({0}.{1}* {2} = &{3}.{4})", + Context.Parameter.QualifiedType, Helpers.InternalStruct, + arg, Context.Parameter.Name, Helpers.InstanceIdentifier); + Context.Before.WriteOpenBraceAndIndent(); + Context.Return.Write($"new {typePrinter.IntPtrType}({arg})"); + Context.Cleanup.UnindentAndWriteCloseBrace(); } else { Context.Before.WriteLine("var {0} = {1}.{2};", arg, Context.Parameter.Name, Helpers.InstanceIdentifier); + Context.Return.Write($"new {typePrinter.IntPtrType}(&{arg})"); } - Context.Return.Write($"new {typePrinter.IntPtrType}(&{arg})"); return true; } diff --git a/src/Generator/Generators/CSharp/CSharpSources.cs b/src/Generator/Generators/CSharp/CSharpSources.cs index 30145f00..1540de3f 100644 --- a/src/Generator/Generators/CSharp/CSharpSources.cs +++ b/src/Generator/Generators/CSharp/CSharpSources.cs @@ -413,7 +413,7 @@ namespace CppSharp.Generators.CSharp if (@class.IsValueType) { WriteLine($"private {@class.Name}.{Helpers.InternalStruct} {Helpers.InstanceField};"); - WriteLine($"internal {@class.Name}.{Helpers.InternalStruct} {Helpers.InstanceIdentifier} => {Helpers.InstanceField};"); + WriteLine($"internal ref {@class.Name}.{Helpers.InternalStruct} {Helpers.InstanceIdentifier} => ref {Helpers.InstanceField};"); } else { diff --git a/tests/dotnet/CSharp/CSharp.Tests.cs b/tests/dotnet/CSharp/CSharp.Tests.cs index d35eb6ff..1f3a64c2 100644 --- a/tests/dotnet/CSharp/CSharp.Tests.cs +++ b/tests/dotnet/CSharp/CSharp.Tests.cs @@ -1995,4 +1995,11 @@ public unsafe class CSharpTests Assert.IsTrue(CSharp.CSharp.PointerToClass.IsDefaultInstance); Assert.IsTrue(CSharp.CSharp.PointerToClass.IsValid); } + + [Test] + public void TestValueTypeOutParameter() + { + CSharp.CSharp.ValueTypeOutParameter(out var unionTest); + Assert.AreEqual(2, unionTest.A); + } } diff --git a/tests/dotnet/CSharp/CSharp.cpp b/tests/dotnet/CSharp/CSharp.cpp index cffbff4b..96144f94 100644 --- a/tests/dotnet/CSharp/CSharp.cpp +++ b/tests/dotnet/CSharp/CSharp.cpp @@ -1791,3 +1791,8 @@ bool PointerTester::IsValid() } PointerTester* PointerToClass = &internalPointerTesterInstance; + +void ValueTypeOutParameter(UnionTester* tester) +{ + tester->a = 2; +} diff --git a/tests/dotnet/CSharp/CSharp.h b/tests/dotnet/CSharp/CSharp.h index 504dd7e2..68154b71 100644 --- a/tests/dotnet/CSharp/CSharp.h +++ b/tests/dotnet/CSharp/CSharp.h @@ -1603,3 +1603,10 @@ public: }; DLL_API extern PointerTester* PointerToClass; + +union DLL_API UnionTester { + float a; + int b; +}; + +void DLL_API ValueTypeOutParameter(CS_OUT UnionTester* tester);