From a18479e1db084d9c9c8aa290303db9b5626a31b2 Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Wed, 18 Nov 2015 17:04:25 +0200 Subject: [PATCH] Generated valid code for wrapping char arrays. Signed-off-by: Dimitar Dobrev --- .../Generators/CLI/CLIHeadersTemplate.cs | 4 +++- src/Generator/Generators/CLI/CLIMarshal.cs | 10 ++++++++ .../Generators/CLI/CLISourcesTemplate.cs | 4 +++- .../Generators/CLI/CLITypePrinter.cs | 6 +++++ .../Generators/CSharp/CSharpMarshal.cs | 23 +++++++++++++++---- .../Generators/CSharp/CSharpTextTemplate.cs | 9 ++++++-- .../Generators/CSharp/CSharpTypePrinter.cs | 6 +++++ tests/Common/Common.Tests.cs | 6 +++++ tests/Common/Common.cpp | 4 +--- tests/Common/Common.h | 9 ++++++-- 10 files changed, 67 insertions(+), 14 deletions(-) diff --git a/src/Generator/Generators/CLI/CLIHeadersTemplate.cs b/src/Generator/Generators/CLI/CLIHeadersTemplate.cs index c2d73b65..402900d4 100644 --- a/src/Generator/Generators/CLI/CLIHeadersTemplate.cs +++ b/src/Generator/Generators/CLI/CLIHeadersTemplate.cs @@ -561,7 +561,9 @@ namespace CppSharp.Generators.CLI WriteLine("{0} get();", type); - if (!variable.QualifiedType.Qualifiers.IsConst) + var arrayType = type as ArrayType; + var qualifiedType = arrayType != null ? arrayType.QualifiedType : variable.QualifiedType; + if (!qualifiedType.Qualifiers.IsConst) WriteLine("void set({0});", type); WriteCloseBraceIndent(); diff --git a/src/Generator/Generators/CLI/CLIMarshal.cs b/src/Generator/Generators/CLI/CLIMarshal.cs index 235d2ed3..d6f2a138 100644 --- a/src/Generator/Generators/CLI/CLIMarshal.cs +++ b/src/Generator/Generators/CLI/CLIMarshal.cs @@ -59,6 +59,16 @@ namespace CppSharp.Generators.CLI supportBefore.WriteCloseBraceIndent(); Context.Return.Write(value); break; + case ArrayType.ArraySize.Incomplete: + // const char* and const char[] are the same so we can use a string + if (array.Type.IsPrimitiveType(PrimitiveType.Char) && + array.QualifiedType.Qualifiers.IsConst) + return VisitPointerType(new PointerType + { + QualifiedPointee = array.QualifiedType + }, quals); + goto case ArrayType.ArraySize.Variable; + case ArrayType.ArraySize.Variable: Context.Return.Write("nullptr"); break; diff --git a/src/Generator/Generators/CLI/CLISourcesTemplate.cs b/src/Generator/Generators/CLI/CLISourcesTemplate.cs index 3c95529e..defa65fc 100644 --- a/src/Generator/Generators/CLI/CLISourcesTemplate.cs +++ b/src/Generator/Generators/CLI/CLISourcesTemplate.cs @@ -623,7 +623,9 @@ namespace CppSharp.Generators.CLI { GeneratePropertyGetter(variable, @class, variable.Name, variable.Type); - if (!variable.QualifiedType.Qualifiers.IsConst) + var arrayType = variable.Type as ArrayType; + var qualifiedType = arrayType != null ? arrayType.QualifiedType : variable.QualifiedType; + if (!qualifiedType.Qualifiers.IsConst) GeneratePropertySetter(variable, @class, variable.Name, variable.Type); } diff --git a/src/Generator/Generators/CLI/CLITypePrinter.cs b/src/Generator/Generators/CLI/CLITypePrinter.cs index 1301fe3a..29ce8182 100644 --- a/src/Generator/Generators/CLI/CLITypePrinter.cs +++ b/src/Generator/Generators/CLI/CLITypePrinter.cs @@ -63,6 +63,12 @@ namespace CppSharp.Generators.CLI public string VisitArrayType(ArrayType array, TypeQualifiers quals) { + // const char* and const char[] are the same so we can use a string + if (array.SizeType == ArrayType.ArraySize.Incomplete && + array.Type.IsPrimitiveType(PrimitiveType.Char) && + array.QualifiedType.Qualifiers.IsConst) + return "System::String^"; + return string.Format("cli::array<{0}>^", array.Type.Visit(this)); } diff --git a/src/Generator/Generators/CSharp/CSharpMarshal.cs b/src/Generator/Generators/CSharp/CSharpMarshal.cs index 7aba8cda..fc368704 100644 --- a/src/Generator/Generators/CSharp/CSharpMarshal.cs +++ b/src/Generator/Generators/CSharp/CSharpMarshal.cs @@ -91,7 +91,6 @@ namespace CppSharp.Generators.CSharp if (!VisitType(array, quals)) return false; - Class @class; switch (array.SizeType) { case ArrayType.ArraySize.Constant: @@ -105,14 +104,28 @@ namespace CppSharp.Generators.CSharp if (array.Type.IsPointerToPrimitiveType(PrimitiveType.Void)) supportBefore.WriteLineIndent("{0}[i] = new global::System.IntPtr({1}[i]);", value, Context.ReturnVarName); - else if (array.Type.Desugar().TryGetClass(out @class) && @class.IsRefType) - supportBefore.WriteLineIndent("{0}[i] = {1}.{2}(*(({1}.Internal*)&({3}[i * sizeof({1}.Internal)])));", - value, array.Type, Helpers.CreateInstanceIdentifier, Context.ReturnVarName); else - supportBefore.WriteLineIndent("{0}[i] = {1}[i];", value, Context.ReturnVarName); + { + Class @class; + if (array.Type.Desugar().TryGetClass(out @class) && @class.IsRefType) + supportBefore.WriteLineIndent("{0}[i] = {1}.{2}(*(({1}.Internal*)&({3}[i * sizeof({1}.Internal)])));", + value, array.Type, Helpers.CreateInstanceIdentifier, Context.ReturnVarName); + else + supportBefore.WriteLineIndent("{0}[i] = {1}[i];", value, Context.ReturnVarName); + } supportBefore.WriteCloseBraceIndent(); Context.Return.Write(value); break; + case ArrayType.ArraySize.Incomplete: + // const char* and const char[] are the same so we can use a string + if (array.Type.IsPrimitiveType(PrimitiveType.Char) && + array.QualifiedType.Qualifiers.IsConst) + return VisitPointerType(new PointerType + { + QualifiedPointee = array.QualifiedType + }, quals); + + goto case ArrayType.ArraySize.Variable; case ArrayType.ArraySize.Variable: Context.Return.Write("null"); break; diff --git a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs index 1d12140f..f09146fe 100644 --- a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs +++ b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs @@ -1017,9 +1017,14 @@ namespace CppSharp.Generators.CSharp var location = string.Format("CppSharp.SymbolResolver.ResolveSymbol(\"{0}\", \"{1}\")", libSymbol.Item1, libSymbol.Item2); - var isRefTypeArray = decl.Type is ArrayType && @class != null && @class.IsRefType; + var arrayType = decl.Type as ArrayType; + var isRefTypeArray = arrayType != null && @class != null && @class.IsRefType; if (isRefTypeArray) - WriteLine("var {0} = (byte*){1};", Generator.GeneratedIdentifier("ptr"), location); + WriteLine("var {0} = {1}{2};", Generator.GeneratedIdentifier("ptr"), + arrayType.Type.IsPrimitiveType(PrimitiveType.Char) && + arrayType.QualifiedType.Qualifiers.IsConst + ? string.Empty : "(byte*)", + location); else WriteLine("var {0} = ({1}*){2};", Generator.GeneratedIdentifier("ptr"), @var.Type, location); diff --git a/src/Generator/Generators/CSharp/CSharpTypePrinter.cs b/src/Generator/Generators/CSharp/CSharpTypePrinter.cs index 27a65aa1..2640be71 100644 --- a/src/Generator/Generators/CSharp/CSharpTypePrinter.cs +++ b/src/Generator/Generators/CSharp/CSharpTypePrinter.cs @@ -153,6 +153,12 @@ namespace CppSharp.Generators.CSharp }; } + // const char* and const char[] are the same so we can use a string + if (array.SizeType == ArrayType.ArraySize.Incomplete && + array.Type.IsPrimitiveType(PrimitiveType.Char) && + array.QualifiedType.Qualifiers.IsConst) + return "string"; + return string.Format("{0}[]", array.Type.Visit(this)); // C# only supports fixed arrays in unsafe sections diff --git a/tests/Common/Common.Tests.cs b/tests/Common/Common.Tests.cs index 89cd8d2e..58dcfdb9 100644 --- a/tests/Common/Common.Tests.cs +++ b/tests/Common/Common.Tests.cs @@ -565,6 +565,12 @@ public class CommonTests : GeneratorTestFixture } } + [Test] + public void TestIncompleteCharArray() + { + Assert.That(Foo.charArray, Is.EqualTo("abc")); + } + private class CustomDerivedFromVirtual : AbstractWithVirtualDtor { public override void @abstract() diff --git a/tests/Common/Common.cpp b/tests/Common/Common.cpp index 5d8c9393..81df2dc2 100644 --- a/tests/Common/Common.cpp +++ b/tests/Common/Common.cpp @@ -14,11 +14,9 @@ Foo::Foo(Private p) { } -const int Foo::unsafe; - const char* Foo::GetANSI() { - return "ANSI"; + return "ANSI"; } void Foo::TakesTypedefedPtr(FooPtr date) diff --git a/tests/Common/Common.h b/tests/Common/Common.h index c4af3b40..b3f4d633 100644 --- a/tests/Common/Common.h +++ b/tests/Common/Common.h @@ -45,9 +45,10 @@ public: IgnoredType ignoredType; int fixedArray[3]; void* ptr; - static const int unsafe = 10; + static const int unsafe; + static const char charArray[]; - const char* GetANSI(); + const char* GetANSI(); // Not properly handled yet - ignore float nested_array[2][2]; @@ -62,6 +63,10 @@ public: bool operator ==(const Foo& other) const; }; +// HACK: do not move these to the cpp - C++/CLI is buggy and cannot link static fields initialised in the cpp +const int Foo::unsafe = 10; +const char Foo::charArray[] = "abc"; + struct DLL_API Bar { enum Item