diff --git a/src/Generator/Generators/CLI/CLIMarshal.cs b/src/Generator/Generators/CLI/CLIMarshal.cs index 8167506a..b656628b 100644 --- a/src/Generator/Generators/CLI/CLIMarshal.cs +++ b/src/Generator/Generators/CLI/CLIMarshal.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Text; using CppSharp.AST; using CppSharp.AST.Extensions; +using CppSharp.Generators.CSharp; using CppSharp.Types; using Delegate = CppSharp.AST.Delegate; using Type = CppSharp.AST.Type; @@ -73,10 +74,10 @@ namespace CppSharp.Generators.CLI return true; } - if (pointee.IsPrimitiveType(PrimitiveType.Char)) + if (CSharpTypePrinter.IsConstCharString(pointer)) { - Context.Return.Write("clix::marshalString({0})", - Context.ReturnVarName); + Context.Return.Write(MarshalStringToManaged(Context.ReturnVarName, + pointer.Pointee.Desugar() as BuiltinType)); return true; } @@ -95,11 +96,12 @@ namespace CppSharp.Generators.CLI if (quals.IsConst != Context.ReturnType.Qualifiers.IsConst) { var nativeTypePrinter = new CppTypePrinter(Context.Driver.TypeDatabase, false); + var returnType = Context.ReturnType.Type.Desugar(); var constlessPointer = new PointerType() { IsDependent = pointer.IsDependent, Modifier = pointer.Modifier, - QualifiedPointee = new QualifiedType(Context.ReturnType.Type.GetPointee()) + QualifiedPointee = new QualifiedType(returnType.GetPointee()) }; var nativeConstlessTypeName = constlessPointer.Visit(nativeTypePrinter, new TypeQualifiers()); returnVarName = string.Format("const_cast<{0}>({1})", @@ -138,6 +140,25 @@ namespace CppSharp.Generators.CLI return pointer.Pointee.Visit(this, quals); } + private string MarshalStringToManaged(string varName, BuiltinType type) + { + var encoding = type.Type == PrimitiveType.Char ? + Encoding.ASCII : Encoding.Unicode; + + if (Equals(encoding, Encoding.ASCII)) + encoding = Context.Driver.Options.Encoding; + + if (Equals(encoding, Encoding.ASCII)) + return string.Format("clix::marshalString({0})", varName); + + if (Equals(encoding, Encoding.Unicode) || + Equals(encoding, Encoding.BigEndianUnicode)) + return string.Format("clix::marshalString({0})", varName); + + throw new NotSupportedException(string.Format("{0} is not supported yet.", + Context.Driver.Options.Encoding.EncodingName)); + } + public override bool VisitMemberPointerType(MemberPointerType member, TypeQualifiers quals) { diff --git a/src/Generator/Generators/CLI/CLITypePrinter.cs b/src/Generator/Generators/CLI/CLITypePrinter.cs index 86f1c804..92916b8c 100644 --- a/src/Generator/Generators/CLI/CLITypePrinter.cs +++ b/src/Generator/Generators/CLI/CLITypePrinter.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using CppSharp.AST; using CppSharp.AST.Extensions; +using CppSharp.Generators.CSharp; using CppSharp.Types; using Type = CppSharp.AST.Type; @@ -139,10 +140,8 @@ namespace CppSharp.Generators.CLI return string.Format("{0}^", function.Visit(this, quals)); } - if (pointee.IsPrimitiveType(PrimitiveType.Char) && quals.IsConst) - { + if (CSharpTypePrinter.IsConstCharString(pointer)) return "System::String^"; - } // From http://msdn.microsoft.com/en-us/library/y31yhkeb.aspx // Any of the following types may be a pointer type: diff --git a/src/Generator/Generators/CSharp/CSharpMarshal.cs b/src/Generator/Generators/CSharp/CSharpMarshal.cs index b7f88df6..03dddec8 100644 --- a/src/Generator/Generators/CSharp/CSharpMarshal.cs +++ b/src/Generator/Generators/CSharp/CSharpMarshal.cs @@ -146,7 +146,8 @@ namespace CppSharp.Generators.CSharp if (CSharpTypePrinter.IsConstCharString(pointer)) { - Context.Return.Write(MarshalStringToManaged(Context.ReturnVarName)); + Context.Return.Write(MarshalStringToManaged(Context.ReturnVarName, + pointer.Pointee.Desugar() as BuiltinType)); return true; } @@ -167,17 +168,21 @@ namespace CppSharp.Generators.CSharp return pointer.Pointee.Visit(this, quals); } - private string MarshalStringToManaged(string varName) + private string MarshalStringToManaged(string varName, BuiltinType type) { - if (Equals(Context.Driver.Options.Encoding, Encoding.ASCII)) - { + var encoding = type.Type == PrimitiveType.Char ? + Encoding.ASCII : Encoding.Unicode; + + if (Equals(encoding, Encoding.ASCII)) + encoding = Context.Driver.Options.Encoding; + + if (Equals(encoding, Encoding.ASCII)) return string.Format("Marshal.PtrToStringAnsi({0})", varName); - } - if (Equals(Context.Driver.Options.Encoding, Encoding.Unicode) || - Equals(Context.Driver.Options.Encoding, Encoding.BigEndianUnicode)) - { + + if (Equals(encoding, Encoding.Unicode) || + Equals(encoding, Encoding.BigEndianUnicode)) return string.Format("Marshal.PtrToStringUni({0})", varName); - } + throw new NotSupportedException(string.Format("{0} is not supported yet.", Context.Driver.Options.Encoding.EncodingName)); } diff --git a/src/Generator/Generators/CSharp/CSharpTypePrinter.cs b/src/Generator/Generators/CSharp/CSharpTypePrinter.cs index 073e9260..3be5a3c6 100644 --- a/src/Generator/Generators/CSharp/CSharpTypePrinter.cs +++ b/src/Generator/Generators/CSharp/CSharpTypePrinter.cs @@ -176,8 +176,9 @@ namespace CppSharp.Generators.CSharp var pointee = pointer.Pointee.Desugar(); return (pointee.IsPrimitiveType(PrimitiveType.Char) || + pointee.IsPrimitiveType(PrimitiveType.Char16) || pointee.IsPrimitiveType(PrimitiveType.WideChar)) && - pointer.QualifiedPointee.Qualifiers.IsConst; + pointer.QualifiedPointee.Qualifiers.IsConst; } public static bool IsConstCharString(QualifiedType qualType) diff --git a/src/Generator/Types/CppTypePrinter.cs b/src/Generator/Types/CppTypePrinter.cs index cbfbe519..e71c94c5 100644 --- a/src/Generator/Types/CppTypePrinter.cs +++ b/src/Generator/Types/CppTypePrinter.cs @@ -103,7 +103,7 @@ namespace CppSharp.Types case PrimitiveType.Bool: return "bool"; case PrimitiveType.Void: return "void"; case PrimitiveType.Char16: - case PrimitiveType.WideChar: return "char"; + case PrimitiveType.WideChar: return "wchar_t"; case PrimitiveType.Char: return "char"; case PrimitiveType.UChar: return "unsigned char"; case PrimitiveType.Short: return "short"; diff --git a/tests/Basic/Basic.Tests.cs b/tests/Basic/Basic.Tests.cs index 18e4bda1..4fe5dfc2 100644 --- a/tests/Basic/Basic.Tests.cs +++ b/tests/Basic/Basic.Tests.cs @@ -369,6 +369,7 @@ public class BasicTests : GeneratorTestFixture Assert.That(prop.FieldValue, Is.EqualTo(10)); } + [Test] public void TestVariable() { // Test field property @@ -377,6 +378,14 @@ public class BasicTests : GeneratorTestFixture Assert.That(TestVariables.VALUE, Is.EqualTo(10)); } + [Test] + public void TestWideStrings() + { + var ws = new TestWideStrings(); + var s = ws.WidePointer; + Assert.That(ws.WidePointer, Is.EqualTo("Hello")); + } + [Test] public unsafe void TestArraysPointers() { diff --git a/tests/Basic/Basic.h b/tests/Basic/Basic.h index aa193627..7c875d52 100644 --- a/tests/Basic/Basic.h +++ b/tests/Basic/Basic.h @@ -508,6 +508,14 @@ struct DLL_API TestVariables int TestVariables::VALUE; void TestVariables::SetValue(int value) { VALUE = value; } +typedef const wchar_t * LPCWSTR; +struct DLL_API TestWideStrings +{ + LPCWSTR GetWidePointer(); +}; + +LPCWSTR TestWideStrings::GetWidePointer() { return L"Hello"; } + enum struct MyEnum { A, B, C }; class DLL_API TestArraysPointers