Browse Source

Reverted the representation of Booleans as managed Booleans except in internal structs.

Managed booleans are more CPU-efficient than bytes, and some problems with code generation are fixed.

Signed-off-by: Dimitar Dobrev <dpldobrev@yahoo.com>
pull/575/head
Dimitar Dobrev 10 years ago
parent
commit
54e8a16fd1
  1. 24
      src/Generator/Generators/CSharp/CSharpMarshal.cs
  2. 14
      src/Generator/Generators/CSharp/CSharpTextTemplate.cs
  3. 72
      src/Generator/Generators/CSharp/CSharpTypePrinter.cs
  4. 4
      src/Generator/Passes/HandleDefaultParamValuesPass.cs
  5. 2
      tests/CSharp/CSharp.cs

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

@ -12,7 +12,9 @@ namespace CppSharp.Generators.CSharp
public enum CSharpMarshalKind public enum CSharpMarshalKind
{ {
Unknown, Unknown,
NativeField NativeField,
GenericDelegate,
DefaultExpression
} }
public class CSharpMarshalContext : MarshalContext public class CSharpMarshalContext : MarshalContext
@ -212,9 +214,13 @@ namespace CppSharp.Generators.CSharp
case PrimitiveType.Char16: case PrimitiveType.Char16:
return false; return false;
case PrimitiveType.Bool: case PrimitiveType.Bool:
// returned structs must be blittable and bool isn't if (Context.Kind == CSharpMarshalKind.NativeField)
Context.Return.Write("{0} != 0", Context.ReturnVarName); {
return true; // returned structs must be blittable and bool isn't
Context.Return.Write("{0} != 0", Context.ReturnVarName);
return true;
}
goto default;
default: default:
Context.Return.Write(Context.ReturnVarName); Context.Return.Write(Context.ReturnVarName);
return true; return true;
@ -579,9 +585,13 @@ namespace CppSharp.Generators.CSharp
case PrimitiveType.Char16: case PrimitiveType.Char16:
return false; return false;
case PrimitiveType.Bool: case PrimitiveType.Bool:
// returned structs must be blittable and bool isn't if (Context.Kind == CSharpMarshalKind.NativeField)
Context.Return.Write("(byte) ({0} ? 1 : 0)", Context.Parameter.Name); {
return true; // returned structs must be blittable and bool isn't
Context.Return.Write("(byte) ({0} ? 1 : 0)", Context.Parameter.Name);
return true;
}
goto default;
default: default:
Context.Return.Write(Context.Parameter.Name); Context.Return.Write(Context.Parameter.Name);
return true; return true;

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

@ -741,7 +741,9 @@ namespace CppSharp.Generators.CSharp
WriteLine("[FieldOffset({0})]", field.OffsetInBytes); WriteLine("[FieldOffset({0})]", field.OffsetInBytes);
TypePrinter.PushMarshalKind(CSharpMarshalKind.NativeField);
var fieldTypePrinted = field.QualifiedType.CSharpType(TypePrinter); var fieldTypePrinted = field.QualifiedType.CSharpType(TypePrinter);
TypePrinter.PopMarshalKind();
var typeName = safeIdentifier; var typeName = safeIdentifier;
if (!string.IsNullOrWhiteSpace(fieldTypePrinted.NameSuffix)) if (!string.IsNullOrWhiteSpace(fieldTypePrinted.NameSuffix))
@ -888,6 +890,7 @@ namespace CppSharp.Generators.CSharp
NewLine(); NewLine();
WriteStartBraceIndent(); WriteStartBraceIndent();
ctx.Kind = CSharpMarshalKind.NativeField;
var marshal = new CSharpMarshalManagedToNativePrinter(ctx); var marshal = new CSharpMarshalManagedToNativePrinter(ctx);
var arrayType = field.Type as ArrayType; var arrayType = field.Type as ArrayType;
@ -2516,13 +2519,6 @@ namespace CppSharp.Generators.CSharp
&& !string.IsNullOrWhiteSpace(param.Context.ArgumentPrefix)) && !string.IsNullOrWhiteSpace(param.Context.ArgumentPrefix))
name.Append(param.Context.ArgumentPrefix); name.Append(param.Context.ArgumentPrefix);
// returned structs must be blittable and bool isn't
if ((param.Param.Type.GetFinalPointee() ?? param.Param.Type).IsPrimitiveType(PrimitiveType.Bool))
{
var typePrinter = new CSharpTypePrinter(Driver);
typePrinter.PushContext(CSharpTypePrinterContextKind.Native);
name.AppendFormat("({0}) ", param.Param.Type.Visit(typePrinter));
}
name.Append(param.Name); name.Append(param.Name);
names.Add(name.ToString()); names.Add(name.ToString());
} }
@ -2702,9 +2698,7 @@ namespace CppSharp.Generators.CSharp
PrimitiveType primitive; PrimitiveType primitive;
// Do not delete instance in MS ABI. // Do not delete instance in MS ABI.
var name = param.Kind == ParameterKind.ImplicitDestructorParameter ? "0" : param.Name; var name = param.Kind == ParameterKind.ImplicitDestructorParameter ? "0" : param.Name;
// returned structs must be blittable and bool and char aren't if (param.Type.IsPrimitiveType(out primitive) && primitive != PrimitiveType.Char)
if (param.Type.IsPrimitiveType(out primitive) &&
primitive != PrimitiveType.Char && primitive != PrimitiveType.Bool)
{ {
return new ParamMarshal { Name = name, Param = param }; return new ParamMarshal { Name = name, Param = param };
} }

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

@ -11,27 +11,14 @@ namespace CppSharp.Generators.CSharp
public enum CSharpTypePrinterContextKind public enum CSharpTypePrinterContextKind
{ {
Native, Native,
Managed, Managed
ManagedPointer,
GenericDelegate,
DefaultExpression
} }
public class CSharpTypePrinterContext : TypePrinterContext public class CSharpTypePrinterContext : TypePrinterContext
{ {
public CSharpTypePrinterContextKind CSharpKind; public CSharpTypePrinterContextKind CSharpKind;
public CSharpMarshalKind MarshalKind;
public QualifiedType FullType; public QualifiedType FullType;
public CSharpTypePrinterContext()
{
}
public CSharpTypePrinterContext(TypePrinterContextKind kind,
CSharpTypePrinterContextKind csharpKind) : base(kind)
{
CSharpKind = csharpKind;
}
} }
public class CSharpTypePrinterResult public class CSharpTypePrinterResult
@ -42,7 +29,7 @@ namespace CppSharp.Generators.CSharp
public static implicit operator CSharpTypePrinterResult(string type) public static implicit operator CSharpTypePrinterResult(string type)
{ {
return new CSharpTypePrinterResult() {Type = type}; return new CSharpTypePrinterResult {Type = type};
} }
public override string ToString() public override string ToString()
@ -57,12 +44,18 @@ namespace CppSharp.Generators.CSharp
private readonly Driver driver; private readonly Driver driver;
private readonly Stack<CSharpTypePrinterContextKind> contexts; private readonly Stack<CSharpTypePrinterContextKind> contexts;
private readonly Stack<CSharpMarshalKind> marshalKinds;
public CSharpTypePrinterContextKind ContextKind public CSharpTypePrinterContextKind ContextKind
{ {
get { return contexts.Peek(); } get { return contexts.Peek(); }
} }
public CSharpMarshalKind MarshalKind
{
get { return marshalKinds.Peek(); }
}
public CSharpTypePrinterContext Context; public CSharpTypePrinterContext Context;
public CSharpTypePrinter(Driver driver) public CSharpTypePrinter(Driver driver)
@ -70,7 +63,9 @@ namespace CppSharp.Generators.CSharp
this.driver = driver; this.driver = driver;
contexts = new Stack<CSharpTypePrinterContextKind>(); contexts = new Stack<CSharpTypePrinterContextKind>();
marshalKinds = new Stack<CSharpMarshalKind>();
PushContext(CSharpTypePrinterContextKind.Managed); PushContext(CSharpTypePrinterContextKind.Managed);
PushMarshalKind(CSharpMarshalKind.Unknown);
Context = new CSharpTypePrinterContext(); Context = new CSharpTypePrinterContext();
} }
@ -85,16 +80,27 @@ namespace CppSharp.Generators.CSharp
return contexts.Pop(); return contexts.Pop();
} }
public void PushMarshalKind(CSharpMarshalKind marshalKind)
{
marshalKinds.Push(marshalKind);
}
public CSharpMarshalKind PopMarshalKind()
{
return marshalKinds.Pop();
}
public CSharpTypePrinterResult VisitTagType(TagType tag, TypeQualifiers quals) public CSharpTypePrinterResult VisitTagType(TagType tag, TypeQualifiers quals)
{ {
if (tag.Declaration == null) if (tag.Declaration == null)
return string.Empty; return string.Empty;
TypeMap typeMap; TypeMap typeMap;
if (this.driver.TypeDatabase.FindTypeMap(tag.Declaration, out typeMap)) if (driver.TypeDatabase.FindTypeMap(tag.Declaration, out typeMap))
{ {
typeMap.Type = tag; typeMap.Type = tag;
Context.CSharpKind = ContextKind; Context.CSharpKind = ContextKind;
Context.MarshalKind = MarshalKind;
Context.Type = tag; Context.Type = tag;
string type = typeMap.CSharpSignature(Context); string type = typeMap.CSharpSignature(Context);
@ -160,12 +166,12 @@ namespace CppSharp.Generators.CSharp
var returnType = function.ReturnType; var returnType = function.ReturnType;
var args = string.Empty; var args = string.Empty;
PushContext(CSharpTypePrinterContextKind.GenericDelegate); PushMarshalKind(CSharpMarshalKind.GenericDelegate);
if (arguments.Count > 0) if (arguments.Count > 0)
args = VisitParameters(function.Parameters, hasNames: false).Type; args = VisitParameters(function.Parameters, hasNames: false).Type;
PopContext(); PopMarshalKind();
if (ContextKind != CSharpTypePrinterContextKind.Managed) if (ContextKind != CSharpTypePrinterContextKind.Managed)
return "global::System.IntPtr"; return "global::System.IntPtr";
@ -180,11 +186,11 @@ namespace CppSharp.Generators.CSharp
if (!string.IsNullOrEmpty(args)) if (!string.IsNullOrEmpty(args))
args = string.Format(", {0}", args); args = string.Format(", {0}", args);
PushContext(CSharpTypePrinterContextKind.GenericDelegate); PushMarshalKind(CSharpMarshalKind.GenericDelegate);
var returnTypePrinterResult = returnType.Visit(this); var returnTypePrinterResult = returnType.Visit(this);
PopContext(); PopMarshalKind();
return string.Format("Func<{0}{1}>", returnTypePrinterResult, args); return string.Format("Func<{0}{1}>", returnTypePrinterResult, args);
} }
@ -215,7 +221,7 @@ namespace CppSharp.Generators.CSharp
return IsConstCharString(qualType.Type); return IsConstCharString(qualType.Type);
} }
bool AllowStrings = true; private bool allowStrings = true;
public CSharpTypePrinterResult VisitPointerType(PointerType pointer, public CSharpTypePrinterResult VisitPointerType(PointerType pointer,
TypeQualifiers quals) TypeQualifiers quals)
@ -230,7 +236,7 @@ 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" : "global::System.IntPtr"; return isManagedContext ? "string" : "global::System.IntPtr";
var desugared = pointee.Desugar(); var desugared = pointee.Desugar();
@ -251,15 +257,15 @@ namespace CppSharp.Generators.CSharp
if (isManagedContext && isRefParam) if (isManagedContext && isRefParam)
return pointee.Visit(this, quals); return pointee.Visit(this, quals);
if (ContextKind == CSharpTypePrinterContextKind.GenericDelegate || if (MarshalKind == CSharpMarshalKind.GenericDelegate ||
pointee.IsPrimitiveType(PrimitiveType.Void)) pointee.IsPrimitiveType(PrimitiveType.Void))
return "global::System.IntPtr"; return "global::System.IntPtr";
// 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;
var result = pointee.Visit(this, quals); var result = pointee.Visit(this, quals);
AllowStrings = true; allowStrings = true;
return !isRefParam && result.Type == "global::System.IntPtr" ? "void**" : result + "*"; return !isRefParam && result.Type == "global::System.IntPtr" ? "void**" : result + "*";
} }
@ -297,9 +303,6 @@ namespace CppSharp.Generators.CSharp
// TODO: Non-function member pointer types are tricky to support. // TODO: Non-function member pointer types are tricky to support.
// Re-visit this. // Re-visit this.
return "global::System.IntPtr"; return "global::System.IntPtr";
throw new InvalidOperationException(
"A function pointer not pointing to a function type.");
} }
public CSharpTypePrinterResult VisitBuiltinType(BuiltinType builtin, public CSharpTypePrinterResult VisitBuiltinType(BuiltinType builtin,
@ -314,10 +317,11 @@ namespace CppSharp.Generators.CSharp
var decl = typedef.Declaration; var decl = typedef.Declaration;
TypeMap typeMap; TypeMap typeMap;
if (this.driver.TypeDatabase.FindTypeMap(decl, out typeMap)) if (driver.TypeDatabase.FindTypeMap(decl, out typeMap))
{ {
typeMap.Type = typedef; typeMap.Type = typedef;
Context.CSharpKind = ContextKind; Context.CSharpKind = ContextKind;
Context.MarshalKind = MarshalKind;
Context.Type = typedef; Context.Type = typedef;
string type = typeMap.CSharpSignature(Context); string type = typeMap.CSharpSignature(Context);
@ -360,7 +364,7 @@ namespace CppSharp.Generators.CSharp
{ {
var decl = template.Template.TemplatedDecl; var decl = template.Template.TemplatedDecl;
TypeMap typeMap = null; TypeMap typeMap;
if (!driver.TypeDatabase.FindTypeMap(template, out typeMap)) if (!driver.TypeDatabase.FindTypeMap(template, out typeMap))
return GetNestedQualifiedName(decl) + return GetNestedQualifiedName(decl) +
(ContextKind == CSharpTypePrinterContextKind.Native (ContextKind == CSharpTypePrinterContextKind.Native
@ -370,6 +374,7 @@ namespace CppSharp.Generators.CSharp
typeMap.Type = template; typeMap.Type = template;
Context.Type = template; Context.Type = template;
Context.CSharpKind = ContextKind; Context.CSharpKind = ContextKind;
Context.MarshalKind = MarshalKind;
var type = GetCSharpSignature(typeMap); var type = GetCSharpSignature(typeMap);
if (!string.IsNullOrEmpty(type)) if (!string.IsNullOrEmpty(type))
@ -389,6 +394,7 @@ namespace CppSharp.Generators.CSharp
private string GetCSharpSignature(TypeMap typeMap) private string GetCSharpSignature(TypeMap typeMap)
{ {
Context.CSharpKind = ContextKind; Context.CSharpKind = ContextKind;
Context.MarshalKind = MarshalKind;
return typeMap.CSharpSignature(Context); return typeMap.CSharpSignature(Context);
} }
@ -493,7 +499,7 @@ namespace CppSharp.Generators.CSharp
{ {
case PrimitiveType.Bool: case PrimitiveType.Bool:
// returned structs must be blittable and bool isn't // returned structs must be blittable and bool isn't
return ContextKind == CSharpTypePrinterContextKind.Native ? return MarshalKind == CSharpMarshalKind.NativeField ?
"byte" : "bool"; "byte" : "bool";
case PrimitiveType.Void: return "void"; case PrimitiveType.Void: return "void";
case PrimitiveType.Char16: case PrimitiveType.Char16:
@ -513,7 +519,7 @@ namespace CppSharp.Generators.CSharp
case PrimitiveType.ULong: case PrimitiveType.ULong:
case PrimitiveType.LongLong: case PrimitiveType.LongLong:
case PrimitiveType.ULongLong: case PrimitiveType.ULongLong:
return GetIntString(primitive, this.driver.TargetInfo); return GetIntString(primitive, driver.TargetInfo);
case PrimitiveType.Float: return "float"; case PrimitiveType.Float: return "float";
case PrimitiveType.Double: return "double"; case PrimitiveType.Double: return "double";
case PrimitiveType.IntPtr: return "global::System.IntPtr"; case PrimitiveType.IntPtr: return "global::System.IntPtr";

4
src/Generator/Passes/HandleDefaultParamValuesPass.cs

@ -117,7 +117,7 @@ namespace CppSharp.Passes
TypeMap typeMap; TypeMap typeMap;
var typePrinter = new CSharpTypePrinter(Driver); var typePrinter = new CSharpTypePrinter(Driver);
typePrinter.PushContext(CSharpTypePrinterContextKind.DefaultExpression); typePrinter.PushMarshalKind(CSharpMarshalKind.DefaultExpression);
var typePrinterResult = type.Visit(typePrinter).Type; var typePrinterResult = type.Visit(typePrinter).Type;
if (Driver.TypeDatabase.FindTypeMap(decl, type, out typeMap)) if (Driver.TypeDatabase.FindTypeMap(decl, type, out typeMap))
{ {
@ -259,7 +259,7 @@ namespace CppSharp.Passes
{ {
var typeInSignature = typeMap.CSharpSignatureType(new CSharpTypePrinterContext var typeInSignature = typeMap.CSharpSignatureType(new CSharpTypePrinterContext
{ {
CSharpKind = CSharpTypePrinterContextKind.DefaultExpression, MarshalKind = CSharpMarshalKind.DefaultExpression,
Type = desugared Type = desugared
}).SkipPointerRefs().Desugar(); }).SkipPointerRefs().Desugar();
Enumeration @enum; Enumeration @enum;

2
tests/CSharp/CSharp.cs

@ -62,7 +62,7 @@ namespace CppSharp.Tests
return Type.IsAddress() ? "QList.Internal*" : "QList.Internal"; return Type.IsAddress() ? "QList.Internal*" : "QList.Internal";
return string.Format("System.Collections.Generic.{0}<{1}>", return string.Format("System.Collections.Generic.{0}<{1}>",
ctx.CSharpKind == CSharpTypePrinterContextKind.DefaultExpression ? "List" : "IList", ctx.MarshalKind == CSharpMarshalKind.DefaultExpression ? "List" : "IList",
ctx.GetTemplateParameterList()); ctx.GetTemplateParameterList());
} }

Loading…
Cancel
Save