From de4879f108375b0c5436d9dac32633c6dec363d7 Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Thu, 12 Sep 2013 18:23:01 +0300 Subject: [PATCH 1/3] Added support for Unicode when marshalling strings. Signed-off-by: Dimitar Dobrev --- src/Generator/Generators/CSharp/CSharpMarshal.cs | 4 ++-- tests/Basic/Basic.Tests.cs | 11 ++++++++++- tests/Basic/Basic.h | 2 ++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/Generator/Generators/CSharp/CSharpMarshal.cs b/src/Generator/Generators/CSharp/CSharpMarshal.cs index 6d414ef3..f523e0c4 100644 --- a/src/Generator/Generators/CSharp/CSharpMarshal.cs +++ b/src/Generator/Generators/CSharp/CSharpMarshal.cs @@ -133,7 +133,7 @@ namespace CppSharp.Generators.CSharp if (CSharpTypePrinter.IsConstCharString(pointer)) { - Context.Return.Write("Marshal.PtrToStringAnsi({0})", + Context.Return.Write("Marshal.PtrToStringUni({0})", Context.ReturnVarName); return true; } @@ -359,7 +359,7 @@ namespace CppSharp.Generators.CSharp type.IsPrimitiveType(PrimitiveType.WideChar)) && pointer.QualifiedPointee.Qualifiers.IsConst) { - Context.Return.Write("Marshal.StringToHGlobalAnsi({0})", + Context.Return.Write("Marshal.StringToHGlobalUni({0})", Helpers.SafeIdentifier(Context.Parameter.Name)); CSharpContext.Cleanup.WriteLine("Marshal.FreeHGlobal({0});", Helpers.SafeIdentifier(Context.ArgName)); diff --git a/tests/Basic/Basic.Tests.cs b/tests/Basic/Basic.Tests.cs index c08ec478..4c637d0f 100644 --- a/tests/Basic/Basic.Tests.cs +++ b/tests/Basic/Basic.Tests.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; using NUnit.Framework; using Basic; @@ -103,5 +103,14 @@ public class BasicTests Assert.That(typeof(Foo2).GetProperty("P", BindingFlags.Instance | BindingFlags.NonPublic), Is.Not.Null); } + + [Test] + public void TestUnicode() + { + Foo foo = new Foo(); + const string georgia = "საქართველო"; + foo.Unicode = georgia; + Assert.That(foo.Unicode, Is.EqualTo(georgia)); + } } \ No newline at end of file diff --git a/tests/Basic/Basic.h b/tests/Basic/Basic.h index 4426f829..ba9aa622 100644 --- a/tests/Basic/Basic.h +++ b/tests/Basic/Basic.h @@ -11,6 +11,8 @@ public: Foo(); int A; float B; + + const char* Unicode; }; class DLL_API Foo2 : public Foo From f38fa134e4a782740774004f4867a22464f8bfbf Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Thu, 12 Sep 2013 19:39:39 +0300 Subject: [PATCH 2/3] Added an option for an encoding. Signed-off-by: Dimitar Dobrev --- src/Generator/Driver.cs | 7 +++- .../Generators/CSharp/CSharpMarshal.cs | 38 +++++++++++++++++-- tests/Basic/Basic.Tests.cs | 4 +- tests/Basic/Basic.cpp | 5 +++ tests/Basic/Basic.h | 2 + 5 files changed, 48 insertions(+), 8 deletions(-) diff --git a/src/Generator/Driver.cs b/src/Generator/Driver.cs index 3bf1e2c1..aa88269a 100644 --- a/src/Generator/Driver.cs +++ b/src/Generator/Driver.cs @@ -1,4 +1,5 @@ -using CppSharp.AST; +using System.Text; +using CppSharp.AST; using CppSharp.Generators; using CppSharp.Generators.CLI; using CppSharp.Generators.CSharp; @@ -226,6 +227,8 @@ namespace CppSharp OutputInteropIncludes = true; MaxIndent = 80; CommentPrefix = "///"; + + Encoding = Encoding.ASCII; } // General options @@ -274,6 +277,8 @@ namespace CppSharp public int MaxIndent; public string CommentPrefix; + public Encoding Encoding { get; set; } + private string inlinesLibraryName; public string InlinesLibraryName { diff --git a/src/Generator/Generators/CSharp/CSharpMarshal.cs b/src/Generator/Generators/CSharp/CSharpMarshal.cs index f523e0c4..e882a36c 100644 --- a/src/Generator/Generators/CSharp/CSharpMarshal.cs +++ b/src/Generator/Generators/CSharp/CSharpMarshal.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text; using CppSharp.AST; using CppSharp.Types; using Type = CppSharp.AST.Type; @@ -133,8 +134,7 @@ namespace CppSharp.Generators.CSharp if (CSharpTypePrinter.IsConstCharString(pointer)) { - Context.Return.Write("Marshal.PtrToStringUni({0})", - Context.ReturnVarName); + Context.Return.Write(MarshalStringToManaged(Context.ReturnVarName)); return true; } @@ -151,6 +151,21 @@ namespace CppSharp.Generators.CSharp return true; } + private string MarshalStringToManaged(string varName) + { + if (Equals(Context.Driver.Options.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)) + { + return string.Format("Marshal.PtrToStringUni({0})", varName); + } + throw new NotSupportedException(string.Format("{0} is not supported yet.", + Context.Driver.Options.Encoding.EncodingName)); + } + public override bool VisitPrimitiveType(PrimitiveType primitive, TypeQualifiers quals) { switch (primitive) @@ -359,8 +374,8 @@ namespace CppSharp.Generators.CSharp type.IsPrimitiveType(PrimitiveType.WideChar)) && pointer.QualifiedPointee.Qualifiers.IsConst) { - Context.Return.Write("Marshal.StringToHGlobalUni({0})", - Helpers.SafeIdentifier(Context.Parameter.Name)); + Context.Return.Write(this.MarshalStringToUnmanaged( + Helpers.SafeIdentifier(Context.Parameter.Name))); CSharpContext.Cleanup.WriteLine("Marshal.FreeHGlobal({0});", Helpers.SafeIdentifier(Context.ArgName)); return true; @@ -402,6 +417,21 @@ namespace CppSharp.Generators.CSharp return pointee.Visit(this, quals); } + private string MarshalStringToUnmanaged(string varName) + { + if (Equals(Context.Driver.Options.Encoding, Encoding.ASCII)) + { + return string.Format("Marshal.StringToHGlobalAnsi({0})", varName); + } + if (Equals(Context.Driver.Options.Encoding, Encoding.Unicode) || + Equals(Context.Driver.Options.Encoding, Encoding.BigEndianUnicode)) + { + return string.Format("Marshal.StringToHGlobalUni({0})", varName); + } + throw new NotSupportedException(string.Format("{0} is not supported yet.", + Context.Driver.Options.Encoding.EncodingName)); + } + public override bool VisitPrimitiveType(PrimitiveType primitive, TypeQualifiers quals) { switch (primitive) diff --git a/tests/Basic/Basic.Tests.cs b/tests/Basic/Basic.Tests.cs index 4c637d0f..84c4c17f 100644 --- a/tests/Basic/Basic.Tests.cs +++ b/tests/Basic/Basic.Tests.cs @@ -108,9 +108,7 @@ public class BasicTests public void TestUnicode() { Foo foo = new Foo(); - const string georgia = "საქართველო"; - foo.Unicode = georgia; - Assert.That(foo.Unicode, Is.EqualTo(georgia)); + Assert.That(foo.GetANSI(), Is.EqualTo("ANSI")); } } \ No newline at end of file diff --git a/tests/Basic/Basic.cpp b/tests/Basic/Basic.cpp index bb9269e4..4d146747 100644 --- a/tests/Basic/Basic.cpp +++ b/tests/Basic/Basic.cpp @@ -4,6 +4,11 @@ Foo::Foo() { } +const char* Foo::GetANSI() +{ + return "ANSI"; +} + Foo2 Foo2::operator<<(signed int i) { Foo2 foo; diff --git a/tests/Basic/Basic.h b/tests/Basic/Basic.h index ba9aa622..45d4f739 100644 --- a/tests/Basic/Basic.h +++ b/tests/Basic/Basic.h @@ -13,6 +13,8 @@ public: float B; const char* Unicode; + + const char* GetANSI(); }; class DLL_API Foo2 : public Foo From 422b0769bab929f5e4965de9ef963241e2234ffc Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Thu, 12 Sep 2013 19:58:02 +0300 Subject: [PATCH 3/3] Added a new test project for Unicode strings. Signed-off-by: Dimitar Dobrev --- tests/Basic/Basic.Tests.cs | 2 +- tests/Basic/Basic.h | 2 -- tests/UTF16/UTF16.Tests.cs | 15 +++++++++++++++ tests/UTF16/UTF16.cpp | 1 + tests/UTF16/UTF16.cs | 33 +++++++++++++++++++++++++++++++++ tests/UTF16/UTF16.h | 13 +++++++++++++ tests/UTF16/premake4.lua | 2 ++ 7 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 tests/UTF16/UTF16.Tests.cs create mode 100644 tests/UTF16/UTF16.cpp create mode 100644 tests/UTF16/UTF16.cs create mode 100644 tests/UTF16/UTF16.h create mode 100644 tests/UTF16/premake4.lua diff --git a/tests/Basic/Basic.Tests.cs b/tests/Basic/Basic.Tests.cs index 84c4c17f..60510542 100644 --- a/tests/Basic/Basic.Tests.cs +++ b/tests/Basic/Basic.Tests.cs @@ -105,7 +105,7 @@ public class BasicTests } [Test] - public void TestUnicode() + public void TestANSI() { Foo foo = new Foo(); Assert.That(foo.GetANSI(), Is.EqualTo("ANSI")); diff --git a/tests/Basic/Basic.h b/tests/Basic/Basic.h index 45d4f739..b63b74cd 100644 --- a/tests/Basic/Basic.h +++ b/tests/Basic/Basic.h @@ -12,8 +12,6 @@ public: int A; float B; - const char* Unicode; - const char* GetANSI(); }; diff --git a/tests/UTF16/UTF16.Tests.cs b/tests/UTF16/UTF16.Tests.cs new file mode 100644 index 00000000..0a4599b6 --- /dev/null +++ b/tests/UTF16/UTF16.Tests.cs @@ -0,0 +1,15 @@ +using NUnit.Framework; +using UTF16; + +[TestFixture] +public class UTF16Tests +{ + [Test] + public void TestFoo() + { + var foo = new Foo(); + const string georgia = "საქართველო"; + foo.Unicode = georgia; + Assert.That(foo.Unicode, Is.EqualTo(georgia)); + } +} diff --git a/tests/UTF16/UTF16.cpp b/tests/UTF16/UTF16.cpp new file mode 100644 index 00000000..566968cf --- /dev/null +++ b/tests/UTF16/UTF16.cpp @@ -0,0 +1 @@ +#include "UTF16.h" \ No newline at end of file diff --git a/tests/UTF16/UTF16.cs b/tests/UTF16/UTF16.cs new file mode 100644 index 00000000..9884d488 --- /dev/null +++ b/tests/UTF16/UTF16.cs @@ -0,0 +1,33 @@ +using System.Text; +using CppSharp.AST; +using CppSharp.Generators; +using CppSharp.Utils; + +namespace CppSharp.Tests +{ + public class UTF16Tests : LibraryTest + { + public UTF16Tests(LanguageGeneratorKind kind) + : base("UTF16", kind) + { + } + + public override void SetupPasses(Driver driver) + { + driver.Options.Encoding = Encoding.Unicode; + } + + public override void Preprocess(Driver driver, Library lib) + { + + } + + static class Program + { + public static void Main(string[] args) + { + ConsoleDriver.Run(new UTF16Tests(LanguageGeneratorKind.CSharp)); + } + } + } +} diff --git a/tests/UTF16/UTF16.h b/tests/UTF16/UTF16.h new file mode 100644 index 00000000..13da5e79 --- /dev/null +++ b/tests/UTF16/UTF16.h @@ -0,0 +1,13 @@ +#if defined(_MSC_VER) +#define DLL_API __declspec(dllexport) +#else +#define DLL_API +#endif + +class DLL_API Foo +{ +public: + const char* Unicode; +}; + +DLL_API int FooCallFoo(Foo* foo); diff --git a/tests/UTF16/premake4.lua b/tests/UTF16/premake4.lua new file mode 100644 index 00000000..d7f9c89d --- /dev/null +++ b/tests/UTF16/premake4.lua @@ -0,0 +1,2 @@ +group "Tests/UTF16" + SetupTestCSharp("UTF16") \ No newline at end of file