diff --git a/src/Generator/Generators/CLI/CLIMarshal.cs b/src/Generator/Generators/CLI/CLIMarshal.cs index 70fcb224..8167506a 100644 --- a/src/Generator/Generators/CLI/CLIMarshal.cs +++ b/src/Generator/Generators/CLI/CLIMarshal.cs @@ -67,15 +67,6 @@ namespace CppSharp.Generators.CLI var pointee = pointer.Pointee.Desugar(); - PrimitiveType primitive; - var param = Context.Parameter; - if (param != null && (param.IsOut || param.IsInOut) && - pointee.IsPrimitiveType(out primitive)) - { - Context.Return.Write(Context.ReturnVarName); - return true; - } - if (pointee.IsPrimitiveType(PrimitiveType.Void)) { Context.Return.Write(Context.ReturnVarName); @@ -89,6 +80,15 @@ namespace CppSharp.Generators.CLI return true; } + PrimitiveType primitive; + var param = Context.Parameter; + if (param != null && (param.IsOut || param.IsInOut) && + pointee.IsPrimitiveType(out primitive)) + { + Context.Return.Write(Context.ReturnVarName); + return true; + } + if (pointee.IsPrimitiveType(out primitive)) { var returnVarName = Context.ReturnVarName; diff --git a/src/Generator/Generators/CLI/CLISourcesTemplate.cs b/src/Generator/Generators/CLI/CLISourcesTemplate.cs index b9568359..c3c9e76c 100644 --- a/src/Generator/Generators/CLI/CLISourcesTemplate.cs +++ b/src/Generator/Generators/CLI/CLISourcesTemplate.cs @@ -1101,7 +1101,12 @@ namespace CppSharp.Generators.CLI var type = paramType.Visit(typePrinter); if (param.IsInOut) + { + if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore)) + Write(marshal.Context.SupportBefore); + WriteLine("{0} {1} = {2};", type, argName, marshal.Context.Return); + } else WriteLine("{0} {1};", type, argName); } diff --git a/src/Generator/Generators/CLI/CLITypePrinter.cs b/src/Generator/Generators/CLI/CLITypePrinter.cs index c4c7c4a1..2c4ef504 100644 --- a/src/Generator/Generators/CLI/CLITypePrinter.cs +++ b/src/Generator/Generators/CLI/CLITypePrinter.cs @@ -155,8 +155,7 @@ namespace CppSharp.Generators.CLI { // Skip one indirection if passed by reference var param = Context.Parameter; - if (param != null && (param.IsOut || param.IsInOut) - && pointee == finalPointee) + if (param != null && (param.IsOut || param.IsInOut)) return pointee.Visit(this, quals); return pointee.Visit(this, quals) + "*"; diff --git a/src/Generator/Generators/CSharp/CSharpMarshal.cs b/src/Generator/Generators/CSharp/CSharpMarshal.cs index 17ec4d89..0366c35d 100644 --- a/src/Generator/Generators/CSharp/CSharpMarshal.cs +++ b/src/Generator/Generators/CSharp/CSharpMarshal.cs @@ -430,8 +430,21 @@ namespace CppSharp.Generators.CSharp pointee.IsPrimitiveType(PrimitiveType.WideChar)) && pointer.QualifiedPointee.Qualifiers.IsConst) { - Context.Return.Write(MarshalStringToUnmanaged(Context.Parameter.Name)); - CSharpContext.Cleanup.WriteLine("Marshal.FreeHGlobal({0});", Context.ArgName); + if (Context.Parameter.IsOut) + { + Context.Return.Write("IntPtr.Zero"); + CSharpContext.ArgumentPrefix.Write("&"); + } + else if (Context.Parameter.IsInOut) + { + Context.Return.Write(MarshalStringToUnmanaged(Context.Parameter.Name)); + CSharpContext.ArgumentPrefix.Write("&"); + } + else + { + Context.Return.Write(MarshalStringToUnmanaged(Context.Parameter.Name)); + CSharpContext.Cleanup.WriteLine("Marshal.FreeHGlobal({0});", Context.ArgName); + } return true; } diff --git a/src/Generator/Generators/CSharp/CSharpTypePrinter.cs b/src/Generator/Generators/CSharp/CSharpTypePrinter.cs index f7aeb255..588a2f89 100644 --- a/src/Generator/Generators/CSharp/CSharpTypePrinter.cs +++ b/src/Generator/Generators/CSharp/CSharpTypePrinter.cs @@ -217,8 +217,7 @@ namespace CppSharp.Generators.CSharp { // Skip one indirection if passed by reference var param = Context.Parameter; - if (isManagedContext && param != null && (param.IsOut || param.IsInOut) - && pointee == finalPointee) + if (isManagedContext && param != null && (param.IsOut || param.IsInOut)) return pointee.Visit(this, quals); if (ContextKind == CSharpTypePrinterContextKind.GenericDelegate) diff --git a/tests/Basic/Basic.Tests.cs b/tests/Basic/Basic.Tests.cs index 013c08d7..78b0ac27 100644 --- a/tests/Basic/Basic.Tests.cs +++ b/tests/Basic/Basic.Tests.cs @@ -57,6 +57,24 @@ public class BasicTests : GeneratorTestFixture Assert.That(hello.RetEnum(Enum.F), Is.EqualTo(-9)); } + [Test] + public void TestPrimitiveConstCharStringInOut() + { + var hello = new Hello(); + + string str; + hello.StringOut(out str); + Assert.That(str, Is.EqualTo("HelloStringOut")); + hello.StringOutRef(out str); + Assert.That(str, Is.EqualTo("HelloStringOutRef")); + str = "Hello"; + hello.StringInOut(ref str); + Assert.That(str, Is.EqualTo("StringInOut")); + str = "Hello"; + hello.StringInOutRef(ref str); + Assert.That(str, Is.EqualTo("StringInOutRef")); + } + [Test] public void TestPrimitiveOutParameters() { diff --git a/tests/Basic/Basic.cpp b/tests/Basic/Basic.cpp index 4db6854a..9d8c6d11 100644 --- a/tests/Basic/Basic.cpp +++ b/tests/Basic/Basic.cpp @@ -1,4 +1,5 @@ #include "Basic.h" +#include Foo::Foo() { @@ -203,6 +204,32 @@ void Hello::EnumInOutRef(CS_IN_OUT Enum& e) e = Enum::F; } +void Hello::StringOut(CS_OUT const char** str) +{ + *str = "HelloStringOut"; +} + +void Hello::StringOutRef(CS_OUT const char*& str) +{ + str = "HelloStringOutRef"; +} + +void Hello::StringInOut(CS_IN_OUT const char** str) +{ + if (strcmp(*str, "Hello") == 0) + *str = "StringInOut"; + else + *str = "Failed"; +} + +void Hello::StringInOutRef(CS_IN_OUT const char*& str) +{ + if (strcmp(str, "Hello") == 0) + str = "StringInOutRef"; + else + str = "Failed"; +} + int unsafeFunction(const Bar& ret, char* testForString, void (*foo)(int)) { return ret.A; diff --git a/tests/Basic/Basic.h b/tests/Basic/Basic.h index 160c129b..cd3e992b 100644 --- a/tests/Basic/Basic.h +++ b/tests/Basic/Basic.h @@ -132,6 +132,11 @@ public: void EnumInOut(CS_IN_OUT Enum* e); void EnumInOutRef(CS_IN_OUT Enum& e); + + void StringOut(CS_OUT const char** str); + void StringOutRef(CS_OUT const char*& str); + void StringInOut(CS_IN_OUT const char** str); + void StringInOutRef(CS_IN_OUT const char*& str); }; class DLL_API AbstractFoo