diff --git a/src/Generator/Generators/CSharp/CSharpMarshal.cs b/src/Generator/Generators/CSharp/CSharpMarshal.cs index 18797aa7..d5cbdb28 100644 --- a/src/Generator/Generators/CSharp/CSharpMarshal.cs +++ b/src/Generator/Generators/CSharp/CSharpMarshal.cs @@ -12,7 +12,9 @@ namespace CppSharp.Generators.CSharp public enum CSharpMarshalKind { Unknown, - NativeField + NativeField, + GenericDelegate, + DefaultExpression } public class CSharpMarshalContext : MarshalContext @@ -212,9 +214,13 @@ namespace CppSharp.Generators.CSharp case PrimitiveType.Char16: return false; case PrimitiveType.Bool: - // returned structs must be blittable and bool isn't - Context.Return.Write("{0} != 0", Context.ReturnVarName); - return true; + if (Context.Kind == CSharpMarshalKind.NativeField) + { + // returned structs must be blittable and bool isn't + Context.Return.Write("{0} != 0", Context.ReturnVarName); + return true; + } + goto default; default: Context.Return.Write(Context.ReturnVarName); return true; @@ -579,9 +585,13 @@ namespace CppSharp.Generators.CSharp case PrimitiveType.Char16: return false; case PrimitiveType.Bool: - // returned structs must be blittable and bool isn't - Context.Return.Write("(byte) ({0} ? 1 : 0)", Context.Parameter.Name); - return true; + if (Context.Kind == CSharpMarshalKind.NativeField) + { + // returned structs must be blittable and bool isn't + Context.Return.Write("(byte) ({0} ? 1 : 0)", Context.Parameter.Name); + return true; + } + goto default; default: Context.Return.Write(Context.Parameter.Name); return true; diff --git a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs index 7e6c1a66..ae43a3e5 100644 --- a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs +++ b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs @@ -741,7 +741,9 @@ namespace CppSharp.Generators.CSharp WriteLine("[FieldOffset({0})]", field.OffsetInBytes); + TypePrinter.PushMarshalKind(CSharpMarshalKind.NativeField); var fieldTypePrinted = field.QualifiedType.CSharpType(TypePrinter); + TypePrinter.PopMarshalKind(); var typeName = safeIdentifier; if (!string.IsNullOrWhiteSpace(fieldTypePrinted.NameSuffix)) @@ -888,6 +890,7 @@ namespace CppSharp.Generators.CSharp NewLine(); WriteStartBraceIndent(); + ctx.Kind = CSharpMarshalKind.NativeField; var marshal = new CSharpMarshalManagedToNativePrinter(ctx); var arrayType = field.Type as ArrayType; @@ -2516,13 +2519,6 @@ namespace CppSharp.Generators.CSharp && !string.IsNullOrWhiteSpace(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); names.Add(name.ToString()); } @@ -2702,9 +2698,7 @@ namespace CppSharp.Generators.CSharp PrimitiveType primitive; // Do not delete instance in MS ABI. 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 && primitive != PrimitiveType.Bool) + if (param.Type.IsPrimitiveType(out primitive) && primitive != PrimitiveType.Char) { return new ParamMarshal { Name = name, Param = param }; } diff --git a/src/Generator/Generators/CSharp/CSharpTypePrinter.cs b/src/Generator/Generators/CSharp/CSharpTypePrinter.cs index 91412ed9..7de041fd 100644 --- a/src/Generator/Generators/CSharp/CSharpTypePrinter.cs +++ b/src/Generator/Generators/CSharp/CSharpTypePrinter.cs @@ -11,27 +11,14 @@ namespace CppSharp.Generators.CSharp public enum CSharpTypePrinterContextKind { Native, - Managed, - ManagedPointer, - GenericDelegate, - DefaultExpression + Managed } public class CSharpTypePrinterContext : TypePrinterContext { public CSharpTypePrinterContextKind CSharpKind; + public CSharpMarshalKind MarshalKind; public QualifiedType FullType; - - public CSharpTypePrinterContext() - { - - } - - public CSharpTypePrinterContext(TypePrinterContextKind kind, - CSharpTypePrinterContextKind csharpKind) : base(kind) - { - CSharpKind = csharpKind; - } } public class CSharpTypePrinterResult @@ -42,7 +29,7 @@ namespace CppSharp.Generators.CSharp public static implicit operator CSharpTypePrinterResult(string type) { - return new CSharpTypePrinterResult() {Type = type}; + return new CSharpTypePrinterResult {Type = type}; } public override string ToString() @@ -57,12 +44,18 @@ namespace CppSharp.Generators.CSharp private readonly Driver driver; private readonly Stack contexts; + private readonly Stack marshalKinds; public CSharpTypePrinterContextKind ContextKind { get { return contexts.Peek(); } } + public CSharpMarshalKind MarshalKind + { + get { return marshalKinds.Peek(); } + } + public CSharpTypePrinterContext Context; public CSharpTypePrinter(Driver driver) @@ -70,7 +63,9 @@ namespace CppSharp.Generators.CSharp this.driver = driver; contexts = new Stack(); + marshalKinds = new Stack(); PushContext(CSharpTypePrinterContextKind.Managed); + PushMarshalKind(CSharpMarshalKind.Unknown); Context = new CSharpTypePrinterContext(); } @@ -85,16 +80,27 @@ namespace CppSharp.Generators.CSharp return contexts.Pop(); } + public void PushMarshalKind(CSharpMarshalKind marshalKind) + { + marshalKinds.Push(marshalKind); + } + + public CSharpMarshalKind PopMarshalKind() + { + return marshalKinds.Pop(); + } + public CSharpTypePrinterResult VisitTagType(TagType tag, TypeQualifiers quals) { if (tag.Declaration == null) return string.Empty; TypeMap typeMap; - if (this.driver.TypeDatabase.FindTypeMap(tag.Declaration, out typeMap)) + if (driver.TypeDatabase.FindTypeMap(tag.Declaration, out typeMap)) { typeMap.Type = tag; Context.CSharpKind = ContextKind; + Context.MarshalKind = MarshalKind; Context.Type = tag; string type = typeMap.CSharpSignature(Context); @@ -160,12 +166,12 @@ namespace CppSharp.Generators.CSharp var returnType = function.ReturnType; var args = string.Empty; - PushContext(CSharpTypePrinterContextKind.GenericDelegate); + PushMarshalKind(CSharpMarshalKind.GenericDelegate); if (arguments.Count > 0) args = VisitParameters(function.Parameters, hasNames: false).Type; - PopContext(); + PopMarshalKind(); if (ContextKind != CSharpTypePrinterContextKind.Managed) return "global::System.IntPtr"; @@ -180,11 +186,11 @@ namespace CppSharp.Generators.CSharp if (!string.IsNullOrEmpty(args)) args = string.Format(", {0}", args); - PushContext(CSharpTypePrinterContextKind.GenericDelegate); + PushMarshalKind(CSharpMarshalKind.GenericDelegate); var returnTypePrinterResult = returnType.Visit(this); - PopContext(); + PopMarshalKind(); return string.Format("Func<{0}{1}>", returnTypePrinterResult, args); } @@ -215,7 +221,7 @@ namespace CppSharp.Generators.CSharp return IsConstCharString(qualType.Type); } - bool AllowStrings = true; + private bool allowStrings = true; public CSharpTypePrinterResult VisitPointerType(PointerType pointer, TypeQualifiers quals) @@ -230,7 +236,7 @@ namespace CppSharp.Generators.CSharp var isManagedContext = ContextKind == CSharpTypePrinterContextKind.Managed; - if (AllowStrings && IsConstCharString(pointer)) + if (allowStrings && IsConstCharString(pointer)) return isManagedContext ? "string" : "global::System.IntPtr"; var desugared = pointee.Desugar(); @@ -251,15 +257,15 @@ namespace CppSharp.Generators.CSharp if (isManagedContext && isRefParam) return pointee.Visit(this, quals); - if (ContextKind == CSharpTypePrinterContextKind.GenericDelegate || + if (MarshalKind == CSharpMarshalKind.GenericDelegate || pointee.IsPrimitiveType(PrimitiveType.Void)) return "global::System.IntPtr"; // Do not allow strings inside primitive arrays case, else we'll get invalid types // like string* for const char **. - AllowStrings = isRefParam; + allowStrings = isRefParam; var result = pointee.Visit(this, quals); - AllowStrings = true; + allowStrings = true; 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. // Re-visit this. return "global::System.IntPtr"; - - throw new InvalidOperationException( - "A function pointer not pointing to a function type."); } public CSharpTypePrinterResult VisitBuiltinType(BuiltinType builtin, @@ -314,10 +317,11 @@ namespace CppSharp.Generators.CSharp var decl = typedef.Declaration; TypeMap typeMap; - if (this.driver.TypeDatabase.FindTypeMap(decl, out typeMap)) + if (driver.TypeDatabase.FindTypeMap(decl, out typeMap)) { typeMap.Type = typedef; Context.CSharpKind = ContextKind; + Context.MarshalKind = MarshalKind; Context.Type = typedef; string type = typeMap.CSharpSignature(Context); @@ -360,7 +364,7 @@ namespace CppSharp.Generators.CSharp { var decl = template.Template.TemplatedDecl; - TypeMap typeMap = null; + TypeMap typeMap; if (!driver.TypeDatabase.FindTypeMap(template, out typeMap)) return GetNestedQualifiedName(decl) + (ContextKind == CSharpTypePrinterContextKind.Native @@ -370,6 +374,7 @@ namespace CppSharp.Generators.CSharp typeMap.Type = template; Context.Type = template; Context.CSharpKind = ContextKind; + Context.MarshalKind = MarshalKind; var type = GetCSharpSignature(typeMap); if (!string.IsNullOrEmpty(type)) @@ -389,6 +394,7 @@ namespace CppSharp.Generators.CSharp private string GetCSharpSignature(TypeMap typeMap) { Context.CSharpKind = ContextKind; + Context.MarshalKind = MarshalKind; return typeMap.CSharpSignature(Context); } @@ -493,7 +499,7 @@ namespace CppSharp.Generators.CSharp { case PrimitiveType.Bool: // returned structs must be blittable and bool isn't - return ContextKind == CSharpTypePrinterContextKind.Native ? + return MarshalKind == CSharpMarshalKind.NativeField ? "byte" : "bool"; case PrimitiveType.Void: return "void"; case PrimitiveType.Char16: @@ -513,7 +519,7 @@ namespace CppSharp.Generators.CSharp case PrimitiveType.ULong: case PrimitiveType.LongLong: case PrimitiveType.ULongLong: - return GetIntString(primitive, this.driver.TargetInfo); + return GetIntString(primitive, driver.TargetInfo); case PrimitiveType.Float: return "float"; case PrimitiveType.Double: return "double"; case PrimitiveType.IntPtr: return "global::System.IntPtr"; diff --git a/src/Generator/Passes/HandleDefaultParamValuesPass.cs b/src/Generator/Passes/HandleDefaultParamValuesPass.cs index a6ae4c2f..8fe0e1ef 100644 --- a/src/Generator/Passes/HandleDefaultParamValuesPass.cs +++ b/src/Generator/Passes/HandleDefaultParamValuesPass.cs @@ -117,7 +117,7 @@ namespace CppSharp.Passes TypeMap typeMap; var typePrinter = new CSharpTypePrinter(Driver); - typePrinter.PushContext(CSharpTypePrinterContextKind.DefaultExpression); + typePrinter.PushMarshalKind(CSharpMarshalKind.DefaultExpression); var typePrinterResult = type.Visit(typePrinter).Type; if (Driver.TypeDatabase.FindTypeMap(decl, type, out typeMap)) { @@ -259,7 +259,7 @@ namespace CppSharp.Passes { var typeInSignature = typeMap.CSharpSignatureType(new CSharpTypePrinterContext { - CSharpKind = CSharpTypePrinterContextKind.DefaultExpression, + MarshalKind = CSharpMarshalKind.DefaultExpression, Type = desugared }).SkipPointerRefs().Desugar(); Enumeration @enum; diff --git a/tests/CSharp/CSharp.cs b/tests/CSharp/CSharp.cs index 3a8ed4a4..3271307c 100644 --- a/tests/CSharp/CSharp.cs +++ b/tests/CSharp/CSharp.cs @@ -62,7 +62,7 @@ namespace CppSharp.Tests return Type.IsAddress() ? "QList.Internal*" : "QList.Internal"; return string.Format("System.Collections.Generic.{0}<{1}>", - ctx.CSharpKind == CSharpTypePrinterContextKind.DefaultExpression ? "List" : "IList", + ctx.MarshalKind == CSharpMarshalKind.DefaultExpression ? "List" : "IList", ctx.GetTemplateParameterList()); }