Browse Source

Marshalled C++ char as Mono/.NET char instead of sbyte for a more friendly API.

Signed-off-by: Dimitar Dobrev <dpldobrev@yahoo.com>
pull/205/head
Dimitar Dobrev 12 years ago
parent
commit
72089a499e
  1. 17
      src/Generator/Generators/CLI/CLISourcesTemplate.cs
  2. 4
      src/Generator/Generators/CLI/CLITypePrinter.cs
  3. 2
      src/Generator/Generators/CSharp/CSharpGenerator.cs
  4. 16
      src/Generator/Generators/CSharp/CSharpTextTemplate.cs
  5. 6
      src/Generator/Generators/CSharp/CSharpTypePrinter.cs
  6. 1
      src/Generator/Options.cs
  7. 13
      tests/Basic/Basic.Tests.cs
  8. 5
      tests/Basic/Basic.cpp
  9. 1
      tests/Basic/Basic.cs
  10. 1
      tests/Basic/Basic.h

17
src/Generator/Generators/CLI/CLISourcesTemplate.cs

@ -816,6 +816,8 @@ namespace CppSharp.Generators.CLI
public void GenerateFunctionCall(Function function, Class @class = null) public void GenerateFunctionCall(Function function, Class @class = null)
{ {
CheckArgumentRange(function);
var retType = function.ReturnType; var retType = function.ReturnType;
var needsReturn = !retType.Type.IsPrimitiveType(PrimitiveType.Void); var needsReturn = !retType.Type.IsPrimitiveType(PrimitiveType.Void);
@ -944,6 +946,21 @@ namespace CppSharp.Generators.CLI
} }
} }
private void CheckArgumentRange(Function method)
{
if (Driver.Options.MarshalCharAsManagedChar)
{
foreach (var param in method.Parameters.Where(
p => p.Type.Desugar().IsPrimitiveType(PrimitiveType.Int8)))
{
WriteLine("if ({0} < System::Char::MinValue || {0} > System::SByte::MaxValue)", param.Name);
WriteLineIndent(
"throw gcnew System::ArgumentException(\"{0} must be in the range {1} - {2}.\");",
param.Name, (int) char.MinValue, sbyte.MaxValue);
}
}
}
private static bool IsNativeMethod(Function function) private static bool IsNativeMethod(Function function)
{ {
var method = function as Method; var method = function as Method;

4
src/Generator/Generators/CLI/CLITypePrinter.cs

@ -172,8 +172,8 @@ namespace CppSharp.Generators.CLI
case PrimitiveType.Bool: return "bool"; case PrimitiveType.Bool: return "bool";
case PrimitiveType.Void: return "void"; case PrimitiveType.Void: return "void";
case PrimitiveType.Char16: case PrimitiveType.Char16:
case PrimitiveType.WideChar: return "char"; case PrimitiveType.WideChar: return "System::Char";
case PrimitiveType.Int8: return "char"; case PrimitiveType.Int8: return Options.MarshalCharAsManagedChar ? "System::Char" : "char";
case PrimitiveType.UInt8: return "unsigned char"; case PrimitiveType.UInt8: return "unsigned char";
case PrimitiveType.Int16: return "short"; case PrimitiveType.Int16: return "short";
case PrimitiveType.UInt16: return "unsigned short"; case PrimitiveType.UInt16: return "unsigned short";

2
src/Generator/Generators/CSharp/CSharpGenerator.cs

@ -11,7 +11,7 @@ namespace CppSharp.Generators.CSharp
public CSharpGenerator(Driver driver) : base(driver) public CSharpGenerator(Driver driver) : base(driver)
{ {
typePrinter = new CSharpTypePrinter(driver.TypeDatabase, driver.ASTContext); typePrinter = new CSharpTypePrinter(driver.TypeDatabase, driver.Options, driver.ASTContext);
expressionPrinter = new CSharpExpressionPrinter(); expressionPrinter = new CSharpExpressionPrinter();
CppSharp.AST.Type.TypePrinterDelegate += type => type.Visit(typePrinter).Type; CppSharp.AST.Type.TypePrinterDelegate += type => type.Visit(typePrinter).Type;
} }

16
src/Generator/Generators/CSharp/CSharpTextTemplate.cs

@ -2099,6 +2099,21 @@ namespace CppSharp.Generators.CSharp
PopBlock(NewLineKind.BeforeNextBlock); PopBlock(NewLineKind.BeforeNextBlock);
} }
private void CheckArgumentRange(Function method)
{
if (Driver.Options.MarshalCharAsManagedChar)
{
foreach (var param in method.Parameters.Where(
p => p.Type.Desugar().IsPrimitiveType(PrimitiveType.Int8)))
{
WriteLine("if ({0} < char.MinValue || {0} > sbyte.MaxValue)", param.Name);
WriteLineIndent(
"throw new global::System.ArgumentException(\"{0} must be in the range {1} - {2}.\");",
param.Name, (int) char.MinValue, sbyte.MaxValue);
}
}
}
private static AccessSpecifier GetValidMethodAccess(Method method) private static AccessSpecifier GetValidMethodAccess(Method method)
{ {
switch (method.Access) switch (method.Access)
@ -2179,6 +2194,7 @@ namespace CppSharp.Generators.CSharp
if (parameters == null) if (parameters == null)
parameters = function.Parameters; parameters = function.Parameters;
CheckArgumentRange(function);
var functionName = string.Format("Internal.{0}", var functionName = string.Format("Internal.{0}",
GetFunctionNativeIdentifier(function)); GetFunctionNativeIdentifier(function));
GenerateFunctionCall(functionName, parameters, function); GenerateFunctionCall(functionName, parameters, function);

6
src/Generator/Generators/CSharp/CSharpTypePrinter.cs

@ -54,6 +54,7 @@ namespace CppSharp.Generators.CSharp
{ {
public ASTContext AstContext { get; set; } public ASTContext AstContext { get; set; }
private readonly ITypeMapDatabase TypeMapDatabase; private readonly ITypeMapDatabase TypeMapDatabase;
private readonly DriverOptions driverOptions;
private readonly Stack<CSharpTypePrinterContextKind> contexts; private readonly Stack<CSharpTypePrinterContextKind> contexts;
@ -64,9 +65,10 @@ namespace CppSharp.Generators.CSharp
public CSharpTypePrinterContext Context; public CSharpTypePrinterContext Context;
public CSharpTypePrinter(ITypeMapDatabase database, ASTContext context) public CSharpTypePrinter(ITypeMapDatabase database, DriverOptions driverOptions, ASTContext context)
{ {
TypeMapDatabase = database; TypeMapDatabase = database;
this.driverOptions = driverOptions;
AstContext = context; AstContext = context;
contexts = new Stack<CSharpTypePrinterContextKind>(); contexts = new Stack<CSharpTypePrinterContextKind>();
@ -367,7 +369,7 @@ namespace CppSharp.Generators.CSharp
case PrimitiveType.Void: return "void"; case PrimitiveType.Void: return "void";
case PrimitiveType.Char16: case PrimitiveType.Char16:
case PrimitiveType.WideChar: return "char"; case PrimitiveType.WideChar: return "char";
case PrimitiveType.Int8: return "sbyte"; case PrimitiveType.Int8: return driverOptions.MarshalCharAsManagedChar ? "char" : "sbyte";
case PrimitiveType.UInt8: return "byte"; case PrimitiveType.UInt8: return "byte";
case PrimitiveType.Int16: return "short"; case PrimitiveType.Int16: return "short";
case PrimitiveType.UInt16: return "ushort"; case PrimitiveType.UInt16: return "ushort";

1
src/Generator/Options.cs

@ -139,6 +139,7 @@ namespace CppSharp
public List<string> CodeFiles { get; private set; } public List<string> CodeFiles { get; private set; }
public readonly List<string> DependentNameSpaces = new List<string>(); public readonly List<string> DependentNameSpaces = new List<string>();
public bool MarshalCharAsManagedChar { get; set; }
} }
public class InvalidOptionException : Exception public class InvalidOptionException : Exception

13
tests/Basic/Basic.Tests.cs

@ -1,6 +1,8 @@
using CppSharp.Utils; using System;
using CppSharp.Utils;
using NUnit.Framework; using NUnit.Framework;
using Basic; using Basic;
using Enum = Basic.Enum;
public class BasicTests : GeneratorTestFixture public class BasicTests : GeneratorTestFixture
{ {
@ -207,5 +209,14 @@ public class BasicTests : GeneratorTestFixture
Assert.That(testCopyConstructorRef.A, Is.EqualTo(copyBar.A)); Assert.That(testCopyConstructorRef.A, Is.EqualTo(copyBar.A));
Assert.That(testCopyConstructorRef.B, Is.EqualTo(copyBar.B)); Assert.That(testCopyConstructorRef.B, Is.EqualTo(copyBar.B));
} }
[Test]
public void TestCharMarshalling()
{
Foo2 foo2 = new Foo2();
for (char c = char.MinValue; c <= sbyte.MaxValue; c++)
Assert.That(foo2.testCharMarshalling(c), Is.EqualTo(c));
Assert.Catch<ArgumentException>(() => foo2.testCharMarshalling('ж'));
}
} }

5
tests/Basic/Basic.cpp

@ -23,6 +23,11 @@ Foo2 Foo2::operator<<(signed long l)
return foo; return foo;
} }
char Foo2::testCharMarshalling(char c)
{
return c;
}
Bar::Bar() Bar::Bar()
{ {
} }

1
tests/Basic/Basic.cs

@ -17,6 +17,7 @@ namespace CppSharp.Tests
if (driver.Options.IsCSharpGenerator) if (driver.Options.IsCSharpGenerator)
driver.Options.GenerateAbstractImpls = true; driver.Options.GenerateAbstractImpls = true;
driver.Options.GenerateVirtualTables = true; driver.Options.GenerateVirtualTables = true;
driver.Options.MarshalCharAsManagedChar = true;
} }
public override void Preprocess(Driver driver, ASTContext ctx) public override void Preprocess(Driver driver, ASTContext ctx)

1
tests/Basic/Basic.h

@ -48,6 +48,7 @@ public:
Foo2 operator<<(signed int i); Foo2 operator<<(signed int i);
Foo2 operator<<(signed long l); Foo2 operator<<(signed long l);
Bar valueTypeField; Bar valueTypeField;
char testCharMarshalling(char c);
}; };
DLL_API Bar::Item operator |(Bar::Item left, Bar::Item right); DLL_API Bar::Item operator |(Bar::Item left, Bar::Item right);

Loading…
Cancel
Save