Browse Source

Switched the C# generator from manual conversion between strings and pointers to the built-in string marshallers.

Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
pull/696/head
Dimitar Dobrev 9 years ago
parent
commit
e2690ba078
  1. 26
      src/Generator/Generators/CSharp/CSharpMarshal.cs
  2. 9
      src/Generator/Generators/CSharp/CSharpSources.cs
  3. 21
      src/Generator/Generators/CSharp/CSharpTypePrinter.cs
  4. 23
      tests/CSharp/CSharp.Tests.cs
  5. 28
      tests/CSharp/CSharp.cpp
  6. 11
      tests/CSharp/CSharp.h

26
src/Generator/Generators/CSharp/CSharpMarshal.cs

@ -13,7 +13,8 @@ namespace CppSharp.Generators.CSharp
Unknown, Unknown,
NativeField, NativeField,
GenericDelegate, GenericDelegate,
DefaultExpression DefaultExpression,
VTableReturnValue
} }
public class CSharpMarshalContext : MarshalContext public class CSharpMarshalContext : MarshalContext
@ -160,7 +161,8 @@ namespace CppSharp.Generators.CSharp
var pointee = pointer.Pointee.Desugar(); var pointee = pointer.Pointee.Desugar();
bool marshalPointeeAsString = CSharpTypePrinter.IsConstCharString(pointee) && isRefParam; bool marshalPointeeAsString = CSharpTypePrinter.IsConstCharString(pointee) && isRefParam;
if (CSharpTypePrinter.IsConstCharString(pointer) || marshalPointeeAsString) if ((CSharpTypePrinter.IsConstCharString(pointer) && !MarshalsParameter) ||
marshalPointeeAsString)
{ {
Context.Return.Write(MarshalStringToManaged(Context.ReturnVarName, Context.Return.Write(MarshalStringToManaged(Context.ReturnVarName,
pointer.GetFinalPointee().Desugar() as BuiltinType)); pointer.GetFinalPointee().Desugar() as BuiltinType));
@ -505,9 +507,7 @@ namespace CppSharp.Generators.CSharp
var isRefParam = param != null && (param.IsInOut || param.IsOut); var isRefParam = param != null && (param.IsInOut || param.IsOut);
var pointee = pointer.Pointee.Desugar(); var pointee = pointer.Pointee.Desugar();
bool marshalPointeeAsString = CSharpTypePrinter.IsConstCharString(pointee) && isRefParam; if (CSharpTypePrinter.IsConstCharString(pointee) && isRefParam)
if (CSharpTypePrinter.IsConstCharString(pointer) || marshalPointeeAsString)
{ {
if (param.IsOut) if (param.IsOut)
{ {
@ -555,9 +555,11 @@ namespace CppSharp.Generators.CSharp
return true; return true;
} }
var marshalAsString = CSharpTypePrinter.IsConstCharString(pointer);
var finalPointee = pointer.GetFinalPointee(); var finalPointee = pointer.GetFinalPointee();
PrimitiveType primitive; PrimitiveType primitive;
if (finalPointee.IsPrimitiveType(out primitive) || finalPointee.IsEnumType()) if (finalPointee.IsPrimitiveType(out primitive) || finalPointee.IsEnumType() ||
marshalAsString)
{ {
// From MSDN: "note that a ref or out parameter is classified as a moveable // From MSDN: "note that a ref or out parameter is classified as a moveable
// variable". This means we must create a local variable to hold the result // variable". This means we must create a local variable to hold the result
@ -576,13 +578,19 @@ namespace CppSharp.Generators.CSharp
} }
else else
{ {
if (Context.Driver.Options.MarshalCharAsManagedChar && primitive == PrimitiveType.Char) if (!marshalAsString &&
Context.Driver.Options.MarshalCharAsManagedChar &&
primitive == PrimitiveType.Char)
{ {
var typePrinter = new CSharpTypePrinter(Context.Driver);
typePrinter.PushContext(CSharpTypePrinterContextKind.Native); typePrinter.PushContext(CSharpTypePrinterContextKind.Native);
Context.Return.Write(string.Format("({0}) ", pointer.Visit(typePrinter))); Context.Return.Write(string.Format("({0}) ", pointer.Visit(typePrinter)));
typePrinter.PopContext();
} }
Context.Return.Write(Context.Parameter.Name); if (marshalAsString && (Context.Kind == CSharpMarshalKind.NativeField ||
Context.Kind == CSharpMarshalKind.VTableReturnValue))
Context.Return.Write(MarshalStringToUnmanaged(Context.Parameter.Name));
else
Context.Return.Write(Context.Parameter.Name);
} }
return true; return true;

9
src/Generator/Generators/CSharp/CSharpSources.cs

@ -670,8 +670,7 @@ namespace CppSharp.Generators.CSharp
{ {
TypePrinter.PushContext(CSharpTypePrinterContextKind.Native); TypePrinter.PushContext(CSharpTypePrinterContextKind.Native);
var retParam = new Parameter { QualifiedType = function.ReturnType }; retType = function.ReturnType.CSharpType(TypePrinter);
retType = retParam.CSharpType(TypePrinter);
var @params = function.GatherInternalParams(Driver.Options.IsItaniumLikeAbi).Select(p => var @params = function.GatherInternalParams(Driver.Options.IsItaniumLikeAbi).Select(p =>
string.Format("{0} {1}", p.CSharpType(TypePrinter), p.Name)).ToList(); string.Format("{0} {1}", p.CSharpType(TypePrinter), p.Name)).ToList();
@ -962,7 +961,8 @@ namespace CppSharp.Generators.CSharp
if (marshal.Context.Return.StringBuilder.Length > 0) if (marshal.Context.Return.StringBuilder.Length > 0)
{ {
WriteLine("{0} = {1}{2};", ctx.ReturnVarName, WriteLine("{0} = {1}{2};", ctx.ReturnVarName,
field.Type.IsPointer() && field.Type.GetFinalPointee().IsPrimitiveType() ? field.Type.IsPointer() && field.Type.GetFinalPointee().IsPrimitiveType() &&
!CSharpTypePrinter.IsConstCharString(field.Type) ?
string.Format("({0}) ", CSharpTypePrinter.IntPtrType) : string.Format("({0}) ", CSharpTypePrinter.IntPtrType) :
string.Empty, string.Empty,
marshal.Context.Return); marshal.Context.Return);
@ -1659,7 +1659,8 @@ namespace CppSharp.Generators.CSharp
{ {
ArgName = Helpers.ReturnIdentifier, ArgName = Helpers.ReturnIdentifier,
Parameter = param, Parameter = param,
Function = method Function = method,
Kind = CSharpMarshalKind.VTableReturnValue
}; };
var marshal = new CSharpMarshalManagedToNativePrinter(ctx); var marshal = new CSharpMarshalManagedToNativePrinter(ctx);

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

@ -6,6 +6,7 @@ using CppSharp.Types;
using Type = CppSharp.AST.Type; using Type = CppSharp.AST.Type;
using ParserTargetInfo = CppSharp.Parser.ParserTargetInfo; using ParserTargetInfo = CppSharp.Parser.ParserTargetInfo;
using System.Linq; using System.Linq;
using System.Text;
namespace CppSharp.Generators.CSharp namespace CppSharp.Generators.CSharp
{ {
@ -265,7 +266,19 @@ namespace CppSharp.Generators.CSharp
var isManagedContext = ContextKind == CSharpTypePrinterContextKind.Managed; var isManagedContext = ContextKind == CSharpTypePrinterContextKind.Managed;
if (allowStrings && IsConstCharString(pointer)) if (allowStrings && IsConstCharString(pointer))
return isManagedContext ? "string" : IntPtrType; {
if (isManagedContext || MarshalKind == CSharpMarshalKind.GenericDelegate)
return "string";
if (Context.Parameter == null || Context.Parameter.Name == Helpers.ReturnIdentifier)
return IntPtrType;
if (driver.Options.Encoding == Encoding.ASCII)
return string.Format("[MarshalAs(UnmanagedType.LPStr)] string");
if (driver.Options.Encoding == Encoding.Unicode ||
driver.Options.Encoding == Encoding.BigEndianUnicode)
return string.Format("[MarshalAs(UnmanagedType.LPWStr)] string");
throw new NotSupportedException(string.Format("{0} is not supported yet.",
driver.Options.Encoding.EncodingName));
}
var desugared = pointee.Desugar(); var desugared = pointee.Desugar();
@ -288,6 +301,9 @@ namespace CppSharp.Generators.CSharp
if (pointee.IsPrimitiveType(PrimitiveType.Void)) if (pointee.IsPrimitiveType(PrimitiveType.Void))
return IntPtrType; return IntPtrType;
if (IsConstCharString(pointee) && isRefParam)
return IntPtrType + "*";
// Do not allow strings inside primitive arrays case, else we'll get invalid types // Do not allow strings inside primitive arrays case, else we'll get invalid types
// like string* for const char **. // like string* for const char **.
allowStrings = isRefParam; allowStrings = isRefParam;
@ -300,9 +316,6 @@ namespace CppSharp.Generators.CSharp
Enumeration @enum; Enumeration @enum;
if (desugared.TryGetEnum(out @enum)) if (desugared.TryGetEnum(out @enum))
{ {
if (MarshalKind == CSharpMarshalKind.GenericDelegate && isManagedContext)
return IntPtrType;
// Skip one indirection if passed by reference // Skip one indirection if passed by reference
var param = Context.Parameter; var param = Context.Parameter;
if (isManagedContext && param != null && (param.IsOut || param.IsInOut) if (isManagedContext && param != null && (param.IsOut || param.IsInOut)

23
tests/CSharp/CSharp.Tests.cs

@ -555,6 +555,29 @@ public unsafe class CSharpTests : GeneratorTestFixture
} }
} }
[Test]
public void TestOverrideVirtualWithString()
{
using (var overrideVirtualWithString = new OverrideVirtualWithString())
{
Assert.That(overrideVirtualWithString.CallsVirtualToReturnString("test"), Is.EqualTo("test_test"));
Assert.IsFalse(overrideVirtualWithString.CallsVirtualToReturnBool(true));
}
}
private class OverrideVirtualWithString : HasVirtualTakesReturnsProblematicTypes
{
public override string VirtualTakesAndReturnsString(string c)
{
return "test_test";
}
public override bool VirtualTakesAndReturnsBool(bool b)
{
return !base.VirtualTakesAndReturnsBool(b);
}
}
private class GetEnumFromNativePointer : UsesPointerToEnumInParamOfVirtual private class GetEnumFromNativePointer : UsesPointerToEnumInParamOfVirtual
{ {
public override Flags HasPointerToEnumInParam(Flags pointerToEnum) public override Flags HasPointerToEnumInParam(Flags pointerToEnum)

28
tests/CSharp/CSharp.cpp

@ -1036,3 +1036,31 @@ bool VirtualDtorAddedInDerived::dtorCalled = false;
void NamespaceB::B::Function(CS_OUT NamespaceA::A &a) void NamespaceB::B::Function(CS_OUT NamespaceA::A &a)
{ {
} }
HasVirtualTakesReturnsProblematicTypes::HasVirtualTakesReturnsProblematicTypes()
{
}
HasVirtualTakesReturnsProblematicTypes::~HasVirtualTakesReturnsProblematicTypes()
{
}
const char* HasVirtualTakesReturnsProblematicTypes::virtualTakesAndReturnsString(const char* c)
{
return c;
}
const char* HasVirtualTakesReturnsProblematicTypes::callsVirtualToReturnString(const char* c)
{
return virtualTakesAndReturnsString(c);
}
bool HasVirtualTakesReturnsProblematicTypes::virtualTakesAndReturnsBool(bool b)
{
return b;
}
bool HasVirtualTakesReturnsProblematicTypes::callsVirtualToReturnBool(bool b)
{
return virtualTakesAndReturnsBool(b);
}

11
tests/CSharp/CSharp.h

@ -969,3 +969,14 @@ private:
}; };
class ForwardInOtherUnitButSameModule; class ForwardInOtherUnitButSameModule;
class DLL_API HasVirtualTakesReturnsProblematicTypes
{
public:
HasVirtualTakesReturnsProblematicTypes();
~HasVirtualTakesReturnsProblematicTypes();
virtual const char* virtualTakesAndReturnsString(const char* c);
const char* callsVirtualToReturnString(const char* c);
virtual bool virtualTakesAndReturnsBool(bool b);
bool callsVirtualToReturnBool(bool b);
};

Loading…
Cancel
Save