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 6d414ef3..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.PtrToStringAnsi({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.StringToHGlobalAnsi({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 c08ec478..60510542 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,12 @@ public class BasicTests Assert.That(typeof(Foo2).GetProperty("P", BindingFlags.Instance | BindingFlags.NonPublic), Is.Not.Null); } + + [Test] + public void TestANSI() + { + Foo foo = new Foo(); + 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 4426f829..b63b74cd 100644 --- a/tests/Basic/Basic.h +++ b/tests/Basic/Basic.h @@ -11,6 +11,8 @@ public: Foo(); int A; float B; + + const char* GetANSI(); }; class DLL_API Foo2 : public Foo 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