From 23ca4b2614cf9fddd19ad0eed6a458205afe39fa Mon Sep 17 00:00:00 2001 From: triton Date: Fri, 3 May 2013 14:48:48 +0100 Subject: [PATCH] Added better support for wrapping of static variables. --- src/Bridge/Variable.cs | 2 + src/Generator/Diagnostics.cs | 1 + .../Generators/CSharp/CSharpTextTemplate.cs | 120 ++++++++++++++++-- src/Parser/Parser.cpp | 3 + 4 files changed, 117 insertions(+), 9 deletions(-) diff --git a/src/Bridge/Variable.cs b/src/Bridge/Variable.cs index ef5bc3c3..415aa107 100644 --- a/src/Bridge/Variable.cs +++ b/src/Bridge/Variable.cs @@ -12,5 +12,7 @@ namespace Cxxi public Type Type { get { return QualifiedType.Type; } } public QualifiedType QualifiedType { get; set; } + + public string Mangled { get; set; } } } diff --git a/src/Generator/Diagnostics.cs b/src/Generator/Diagnostics.cs index 442c31b1..47d4dbbb 100644 --- a/src/Generator/Diagnostics.cs +++ b/src/Generator/Diagnostics.cs @@ -5,6 +5,7 @@ namespace Cxxi public enum DiagnosticId { InvalidOperatorOverload + SymbolNotFound } public enum DiagnosticKind diff --git a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs index 7e15b4cb..10141037 100644 --- a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs +++ b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs @@ -254,6 +254,7 @@ namespace Cxxi.Generators.CSharp GenerateClassConstructors(@class); GenerateClassFields(@class); GenerateClassMethods(@class); + GenerateClassVariables(@class); } WriteCloseBraceIndent(); @@ -478,18 +479,74 @@ namespace Cxxi.Generators.CSharp WriteCloseBraceIndent(); } - private string GetPropertyLocation(T decl, Class @class) - where T : Declaration, ITypedDecl + enum PropertyMethodKind + { + Getter, + Setter + } + + private string GetFieldLocation(Field field, string instance, + out bool isRefClass) + { + isRefClass = false; + + var fieldType = field.Type.Desugar(); + var type = field.Type.ToString() + "*"; + + Class fieldClass; + if (fieldType.IsTagDecl(out fieldClass) && fieldClass.IsRefType) + isRefClass = true; + + TagType tagType; + if (fieldType.IsPointerTo(out tagType) + && tagType.IsTagDecl(out fieldClass) && fieldClass.IsRefType) + isRefClass = true; + + if (CSharpTypePrinter.IsConstCharString(field.QualifiedType)) + isRefClass = true; + + if (isRefClass) + type = "void**"; + + var location = string.Format("*({0}) ({1} + {2})", + type, instance, field.OffsetInBytes); + + return location; + } + + private string GetPropertyLocation(T decl, PropertyMethodKind kind, + out bool isRefClass) where T : Declaration, ITypedDecl { + isRefClass = false; + if (decl is Variable) { - return string.Format("::{0}::{1}", - @class.QualifiedOriginalName, decl.OriginalName); + var @var = decl as Variable; + + var symbol = @var.Mangled; + if (!Driver.LibrarySymbols.FindSymbol(ref symbol)) + { + Driver.Diagnostics.EmitError(DiagnosticId.SymbolNotFound, + "symbol \"{0}\" was not found", symbol); + throw new SymbolNotFoundException(symbol); + } + + NativeLibrary library; + Driver.LibrarySymbols.FindLibraryBySymbol(symbol, out library); + + return string.Format("Cxxi.SymbolResolver.ResolveSymbol(\"{0}\", \"{1}\")", + Path.GetFileNameWithoutExtension(library.FileName), symbol); } var field = decl as Field; - return string.Format("*({0}*) (Instance + {1})", field.Type, - field.OffsetInBytes); + + var location = GetFieldLocation(field, "Instance", + out isRefClass); + + if (isRefClass && kind == PropertyMethodKind.Getter) + location = string.Format("new System.IntPtr({0})", location); + + return location; } private void GeneratePropertySetter(T decl, Class @class) @@ -513,12 +570,19 @@ namespace Cxxi.Generators.CSharp var marshal = new CSharpMarshalManagedToNativePrinter(ctx); param.Visit(marshal); - var variable = GetPropertyLocation(decl, @class); + bool isRefClass; + var variable = GetPropertyLocation(decl, PropertyMethodKind.Setter, + out isRefClass); if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore)) Write(marshal.Context.SupportBefore); - WriteLine("{0} = {1};", variable, marshal.Context.Return); + Write("{0} = {1}", variable, marshal.Context.Return); + + if (isRefClass) + Write(".ToPointer()"); + + WriteLine(";"); WriteCloseBraceIndent(); } @@ -529,7 +593,9 @@ namespace Cxxi.Generators.CSharp WriteLine("get"); WriteStartBraceIndent(); - var variable = GetPropertyLocation(decl, @class); + bool isRefClass; + var variable = GetPropertyLocation(decl, PropertyMethodKind.Getter, + out isRefClass); var ctx = new CSharpMarshalContext(Driver) { @@ -583,6 +649,36 @@ namespace Cxxi.Generators.CSharp } } + public void GenerateClassVariables(Class @class) + { + foreach (var variable in @class.Variables) + { + if (variable.Ignore) continue; + + if (variable.Access != AccessSpecifier.Public) + continue; + + var type = variable.Type; + + NewLineIfNeeded(); + GenerateVariable(@class, type, variable); + NeedNewLine(); + } + } + + private void GenerateVariable(Class @class, Type type, Variable variable) + { + WriteLine("public static {0} {1}", type, variable.Name); + WriteStartBraceIndent(); + + GeneratePropertyGetter(variable, @class); + + if (!variable.QualifiedType.Qualifiers.IsConst) + GeneratePropertySetter(variable, @class); + + WriteCloseBraceIndent(); + } + #endregion #region Constructors @@ -1280,4 +1376,10 @@ namespace Cxxi.Generators.CSharp string.Join(", ", @params)); } } + + internal class SymbolNotFoundException : Exception + { + public SymbolNotFoundException(string msg) : base(msg) + {} + } } \ No newline at end of file diff --git a/src/Parser/Parser.cpp b/src/Parser/Parser.cpp index 8d2779c2..5c28f09d 100644 --- a/src/Parser/Parser.cpp +++ b/src/Parser/Parser.cpp @@ -1353,6 +1353,9 @@ Cxxi::Variable^ Parser::WalkVariable(clang::VarDecl *VD) auto TL = VD->getTypeSourceInfo()->getTypeLoc(); Var->QualifiedType = GetQualifiedType(VD->getType(), WalkType(VD->getType(), &TL)); + auto Mangled = GetDeclMangledName(VD, TargetCXXABI::Microsoft, /*IsDependent=*/false); + Var->Mangled = marshalString(Mangled); + return Var; }