diff --git a/src/Mono.VisualC.Interop/ABI/CppAbi.cs b/src/Mono.VisualC.Interop/ABI/CppAbi.cs index 6fce1cd8..8c956b0b 100644 --- a/src/Mono.VisualC.Interop/ABI/CppAbi.cs +++ b/src/Mono.VisualC.Interop/ABI/CppAbi.cs @@ -54,7 +54,7 @@ namespace Mono.VisualC.Interop.ABI { protected static readonly MethodInfo cppip_managedalloc = typeof (CppInstancePtr).GetProperty ("IsManagedAlloc").GetGetMethod (); protected static readonly MethodInfo cppip_getmanaged = typeof (CppInstancePtr).GetMethod ("GetManaged", BindingFlags.Static | BindingFlags.NonPublic); protected static readonly ConstructorInfo cppip_fromnative = typeof (CppInstancePtr).GetConstructor (new Type [] { typeof (IntPtr) }); - protected static readonly ConstructorInfo cppip_fromsize = typeof (CppInstancePtr).GetConstructor (new Type [] { typeof (int) }); + protected static readonly ConstructorInfo cppip_fromsize = typeof (CppInstancePtr).GetConstructor (BindingFlags.Instance | BindingFlags.NonPublic, null, new Type [] { typeof (int) }, null); protected static readonly ConstructorInfo cppip_fromsize_managed = typeof (CppInstancePtr).GetConstructor (BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[] { typeof (int), typeof (object) }, null); protected static readonly ConstructorInfo notimplementedexception = typeof (NotImplementedException).GetConstructor (new Type [] { typeof (string) }); diff --git a/src/Mono.VisualC.Interop/ABI/Impl/ItaniumTypeInfo.cs b/src/Mono.VisualC.Interop/ABI/Impl/ItaniumTypeInfo.cs index 741a9f64..701c2203 100644 --- a/src/Mono.VisualC.Interop/ABI/Impl/ItaniumTypeInfo.cs +++ b/src/Mono.VisualC.Interop/ABI/Impl/ItaniumTypeInfo.cs @@ -38,25 +38,38 @@ namespace Mono.VisualC.Interop.ABI { { } - - // When adding a non-primary base class's complete vtable, we need to reserve space for - // the stuff before the address point of the vtptr.. - // Includes vbase & vcall offsets (virtual inheritance), offset to top, and RTTI info - public override void AddBase (CppTypeInfo baseType) + protected override void AddBase (CppTypeInfo baseType, bool addVTable) { - if (TypeComplete) - return; - if (BaseClasses.Count > 0 && baseType.VirtualMethods.Any ()) { // already have a primary base + // When adding a non-primary base class's complete vtable, we need to reserve space for + // the stuff before the address point of the vtptr.. + // Includes vbase & vcall offsets (virtual inheritance), offset to top, and RTTI info + if (addVTable) { // FIXME: virtual inheritance - virtual_methods.Insert (BaseVTableSlots, null); - virtual_methods.Insert (BaseVTableSlots, null); - BaseVTableSlots += 2; + virtual_methods.Add (null); + virtual_methods.Add (null); + + vt_overrides.Add (2); + vt_delegate_types.Add (2); + } + + base.AddBase (baseType, addVTable); + } + + protected override bool OnVTableDuplicate (ref int iter, PInvokeSignature sig, PInvokeSignature dup) + { + var isOverride = base.OnVTableDuplicate (ref iter, sig, dup); + if (isOverride && sig.Type == MethodType.NativeDtor) { + // also remove that pesky extra dtor + virtual_methods.RemoveAt (iter + 1); + vt_overrides.Remove (1); + vt_delegate_types.Remove (1); + return true; } - base.AddBase (baseType); + return false; } } diff --git a/src/Mono.VisualC.Interop/ABI/Impl/MsvcAbi.cs b/src/Mono.VisualC.Interop/ABI/Impl/MsvcAbi.cs index 440026c2..4615b733 100644 --- a/src/Mono.VisualC.Interop/ABI/Impl/MsvcAbi.cs +++ b/src/Mono.VisualC.Interop/ABI/Impl/MsvcAbi.cs @@ -49,7 +49,7 @@ namespace Mono.VisualC.Interop.ABI { protected override CppTypeInfo MakeTypeInfo (IEnumerable methods) { - return new MsvcTypeInfo (this, methods.Where (m => IsVirtual (m.OrigMethod)), layout_type, wrapper_type); + return new CppTypeInfo (this, methods.Where (m => IsVirtual (m.OrigMethod)), layout_type, wrapper_type); } public override CallingConvention? GetCallingConvention (MethodInfo methodInfo) diff --git a/src/Mono.VisualC.Interop/ABI/Impl/MsvcTypeInfo.cs b/src/Mono.VisualC.Interop/ABI/Impl/MsvcTypeInfo.cs deleted file mode 100644 index 420e5d45..00000000 --- a/src/Mono.VisualC.Interop/ABI/Impl/MsvcTypeInfo.cs +++ /dev/null @@ -1,56 +0,0 @@ -// Author: -// Alexander Corrado (alexander.corrado@gmail.com) -// Andreia Gaita (shana@spoiledcat.net) -// -// Copyright (C) 2010 Alexander Corrado -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -using System; -using System.Linq; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Reflection; - -using Mono.VisualC.Interop.Util; - -namespace Mono.VisualC.Interop.ABI { - public class MsvcTypeInfo : CppTypeInfo { - public MsvcTypeInfo (MsvcAbi abi, IEnumerable virtualMethods, Type nativeLayout, Type wrapperType) - : base (abi, virtualMethods, nativeLayout, wrapperType) - { - } - - // AFIK, MSVC places only its first base's virtual methods in the derived class's - // primary vtable. Subsequent base classes (each?) get another vtable pointer - public override void AddBase (CppTypeInfo baseType) - { - if (TypeComplete) - return; - - if (BaseClasses.Count == 0) - base.AddBase (baseType, false); - else - base.AddBase (baseType, true); - } - - } -} - diff --git a/src/Mono.VisualC.Interop/CppInstancePtr.cs b/src/Mono.VisualC.Interop/CppInstancePtr.cs index 24cb5056..9f3649ff 100644 --- a/src/Mono.VisualC.Interop/CppInstancePtr.cs +++ b/src/Mono.VisualC.Interop/CppInstancePtr.cs @@ -70,6 +70,7 @@ namespace Mono.VisualC.Interop { } // Alloc a new C++ instance + // NOTE: native_vtptr will be set later after native ctor is called internal CppInstancePtr (int nativeSize, object managedWrapper) { // Under the hood, we're secretly subclassing this C++ class to store a @@ -89,7 +90,7 @@ namespace Mono.VisualC.Interop { } // Alloc a new C++ instance when there is no managed wrapper. - public CppInstancePtr (int nativeSize) + internal CppInstancePtr (int nativeSize) { ptr = Marshal.AllocHGlobal (nativeSize); manage_memory = true; @@ -101,6 +102,11 @@ namespace Mono.VisualC.Interop { if (native == IntPtr.Zero) throw new ArgumentOutOfRangeException ("native cannot be null pointer"); + // Kludge! CppInstancePtr doesn't know whether this class is virtual or not, but we'll just assume that either + // way it's at least sizeof(void*) and read what would be the vtptr anyway. Supposedly, if it's not virtual, + // the wrappers won't use this field anyway... + native_vtptr = Marshal.ReadIntPtr (native); + ptr = native; manage_memory = false; } diff --git a/src/Mono.VisualC.Interop/CppTypeInfo.cs b/src/Mono.VisualC.Interop/CppTypeInfo.cs index 62ffbc17..2e6e55bd 100644 --- a/src/Mono.VisualC.Interop/CppTypeInfo.cs +++ b/src/Mono.VisualC.Interop/CppTypeInfo.cs @@ -103,9 +103,9 @@ namespace Mono.VisualC.Interop { public virtual void AddBase (CppTypeInfo baseType) { - - // by default, do not add another vtable for this new base class - AddBase (baseType, false); + // by default, if we already have base class(es), this base's virtual methods are not included before the derived class's + var addVTable = base_classes.Count >= 1; + AddBase (baseType, addVTable); } protected virtual void AddBase (CppTypeInfo baseType, bool addVTable) @@ -114,34 +114,38 @@ namespace Mono.VisualC.Interop { return; base_classes.Add (baseType); - bool addVTablePointer = addVTable || base_classes.Count > 1; + int baseVMethodCount = baseType.virtual_methods.Count; + + if (addVTable) { + // If we are adding a new vtable, don't skew the offsets of the of this subclass's methods. + // Instead append the new virtual methods to the end. + + for (int i = 0; i < baseVMethodCount; i++) + virtual_methods.Add (baseType.virtual_methods [i]); + + vt_delegate_types.Add (baseVMethodCount); + vt_overrides.Add (baseVMethodCount); + + } else { - if (!addVTable) { // If we're not adding a new vtable, then all this base class's virtual methods go in primary vtable // Skew the offsets of this subclass's vmethods to account for the new base vmethods. - int baseVMethodCount = baseType.virtual_methods.Count; for (int i = 0; i < baseVMethodCount; i++) virtual_methods.Insert (BaseVTableSlots + i, baseType.virtual_methods [i]); BaseVTableSlots += baseVMethodCount; - vt_delegate_types.PrependLast (baseType.vt_delegate_types); - //vt_overrides.PrependLast (baseType.vt_overrides); + vt_delegate_types.Add (baseVMethodCount); vt_overrides.Add (baseVMethodCount); - - } else { - // FIXME: Implement this when we get around to msvc again ? } field_offset_padding_without_vtptr += baseType.native_size + (addVTablePointer? baseType.FieldOffsetPadding : baseType.field_offset_padding_without_vtptr); } - public virtual TBase Cast (ICppObject instance) - where TBase : ICppObject + public virtual CppInstancePtr Cast (ICppObject instance, Type targetType) { - var targetType = typeof (TBase); var found = false; int offset = 0; @@ -162,11 +166,7 @@ namespace Mono.VisualC.Interop { // it is Disposed, even if wrappers created here still exist and are pointing to it. :/ // The casted wrapper created here may be Disposed safely though. // FIXME: On NET_4_0 use IntPtr.Add - var cppip = new CppInstancePtr (new IntPtr (instance.Native.Native.ToInt64 () + offset)); - - // Ugh, this requires boxing of cppip AND some slow reflection.. please cache the result of this! - // FIXME: Perhaps Reflection.Emit all possible base casts and eliminate this beast? - return (TBase)Activator.CreateInstance (targetType, cppip); + return new CppInstancePtr (new IntPtr (instance.Native.Native.ToInt64 () + offset)); } public int CountBases (Func predicate) @@ -189,14 +189,10 @@ namespace Mono.VisualC.Interop { TypeComplete = true; - // Tthis predicate ensures that duplicates are only removed - // if declared in different classes (i.e. overridden methods). - // We usually want to allow the same exact virtual methods to appear - // multiple times, in the case of nonvirtual diamond inheritance, for example. - RemoveVTableDuplicates ((pi1, pi2) => !pi1.OrigMethod.Equals (pi2.OrigMethod)); + RemoveVTableDuplicates (); } - protected virtual void RemoveVTableDuplicates (Func pred) + protected virtual void RemoveVTableDuplicates () { // check that any virtual methods overridden in a subclass are only included once var vsignatures = new Dictionary (MethodSignature.EqualityComparer); @@ -208,14 +204,29 @@ namespace Mono.VisualC.Interop { PInvokeSignature existing; if (vsignatures.TryGetValue (sig, out existing)) { - if (pred (sig, existing)) - virtual_methods.RemoveAt (i--); + OnVTableDuplicate (ref i, sig, existing); } else { vsignatures.Add (sig, sig); } } } + protected virtual bool OnVTableDuplicate (ref int iter, PInvokeSignature sig, PInvokeSignature dup) + { + // This predicate ensures that duplicates are only removed + // if declared in different classes (i.e. overridden methods). + // We usually want to allow the same exact virtual methods to appear + // multiple times, in the case of nonvirtual diamond inheritance, for example. + if (!sig.OrigMethod.Equals (dup.OrigMethod)) { + virtual_methods.RemoveAt (iter--); + vt_overrides.Remove (1); + vt_delegate_types.Remove (1); + return true; + } + + return false; + } + public virtual T GetAdjustedVirtualCall (CppInstancePtr instance, int derivedVirtualMethodIndex) where T : class /* Delegate */ { diff --git a/src/Mono.VisualC.Interop/Makefile.am b/src/Mono.VisualC.Interop/Makefile.am index e0df2025..c80df25a 100644 --- a/src/Mono.VisualC.Interop/Makefile.am +++ b/src/Mono.VisualC.Interop/Makefile.am @@ -48,7 +48,6 @@ FILES = \ ABI/Impl/ItaniumAbi.cs \ ABI/Impl/ItaniumTypeInfo.cs \ ABI/Impl/MsvcAbi.cs \ - ABI/Impl/MsvcTypeInfo.cs \ ABI/Impl/VirtualOnlyAbi.cs \ ABI/MethodType.cs \ ABI/VTable.cs \ diff --git a/src/Mono.VisualC.Interop/Mono.VisualC.Interop.csproj b/src/Mono.VisualC.Interop/Mono.VisualC.Interop.csproj index a9e38fe4..640641a0 100644 --- a/src/Mono.VisualC.Interop/Mono.VisualC.Interop.csproj +++ b/src/Mono.VisualC.Interop/Mono.VisualC.Interop.csproj @@ -76,7 +76,6 @@ - diff --git a/src/Mono.VisualC.Interop/Util/LazyGeneratedList.cs b/src/Mono.VisualC.Interop/Util/LazyGeneratedList.cs index da2693ef..48ba5009 100644 --- a/src/Mono.VisualC.Interop/Util/LazyGeneratedList.cs +++ b/src/Mono.VisualC.Interop/Util/LazyGeneratedList.cs @@ -32,50 +32,19 @@ using System.Collections.Generic; namespace Mono.VisualC.Interop.Util { - public class LazyGeneratedList : IList where TItem : class { - - private class Node where TItem : class { - - public LazyGeneratedList List { get; set; } - public Node Next { get; set; } - public Node (LazyGeneratedList list, Node next) - { - this.List = list; - this.Next = next; - } - public void AppendNext (Node node) - { - if (Next == null) - Next = node; - else - Next.AppendNext (node); - } - public TItem this [int index] { - get { - if (index >= List.Count) - return Next [index - List.Count]; - return List [index]; - } - } - } - + public class LazyGeneratedList : IList + where TItem : class + { private TItem [] cache; private Func generator; - private Node previous; - private Node next; - private int lead, content, follow; - - private HashSet removed; + private int count; public LazyGeneratedList (int count, Func generator) { this.cache = new TItem [count]; this.generator = generator; - this.lead = 0; - this.content = count; - this.follow = 0; - this.removed = new HashSet (); + this.count = count; } public IEnumerator GetEnumerator () @@ -89,86 +58,37 @@ namespace Mono.VisualC.Interop.Util { } public int Count { - get { return lead + content + follow; } + get { return count; } } public bool IsReadOnly { get { return true; } } - public TItem this [int index] { + public TItem this [int i] { get { - return ForIndex (index, i => previous [i], i => (cache [i] == null? (cache [i] = generator (i)) : cache [i]), i => next [i]); + // access to cache [i] will throw the IndexOutOfRange exception for us + return cache [i] == null? (cache [i] = generator (i)) : cache [i]; } set { throw new NotSupportedException ("This IList is read only"); } } - private TItem ForIndex (int index, Func leadAction, Func contentAction, Func followAction) - { - if (removed.Contains (index)) - index++; - - if (index < lead) { - if (previous != null && index >= 0) - return leadAction (index); - throw new IndexOutOfRangeException (index.ToString ()); - } - - int realIndex = index - lead; - if (realIndex >= content) { - int followIndex = realIndex - content; - if (next != null && followIndex < follow) - return followAction (followIndex); - throw new IndexOutOfRangeException (index.ToString ()); - } - - return contentAction (realIndex); - } - - /* Visual aid for the behavior of the following methods: - - || - ^ ^ ^ ^ - PrependFirst PrependLast AppendFirst AppendLast - */ - - public void AppendFirst (LazyGeneratedList list) + public void Add (int count) { - follow += list.Count; - next = new Node (list, next); + this.count += count; + // flush cache + cache = new TItem [this.count]; } - - public void AppendLast (LazyGeneratedList list) + public void Remove (int count) { - var node = new Node (list, null); - if (next == null) - next = node; - else - next.AppendNext (node); - - follow += list.Count; + this.count -= count; + // flush cache + cache = new TItem [this.count]; } - public void PrependLast (LazyGeneratedList list) - { - var node = new Node (list, null); - if (previous == null) - previous = node; - else - previous.AppendNext (node); - - lead += list.Count; - } - - public void PrependFirst (LazyGeneratedList list) - { - lead += list.Count; - previous = new Node (list, previous); - } - - // FIXME: Should probably implement these 3 at some point + // FIXME: Should probably implement these at some point public bool Contains (TItem item) { throw new NotImplementedException (); @@ -181,24 +101,13 @@ namespace Mono.VisualC.Interop.Util { { throw new NotImplementedException (); } - - public void Insert (int index, TItem item) { throw new NotImplementedException (); } public void RemoveAt (int index) { - while (removed.Contains (index)) - index++; - - removed.Add (index); - content--; - } - public void Add (int count) - { - content += count; - Array.Resize (ref cache, content); + throw new NotImplementedException (); } public void Add (TItem item) { diff --git a/src/generator/Templates/CSharp/CSharpClass.cs b/src/generator/Templates/CSharp/CSharpClass.cs index c0efbd86..064d6e67 100644 --- a/src/generator/Templates/CSharp/CSharpClass.cs +++ b/src/generator/Templates/CSharp/CSharpClass.cs @@ -19,9 +19,9 @@ namespace Templates { public partial class CSharpClass : Base { - #line 231 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 234 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" -private void WriteMethodHeader (Method method, string initBases) +private void WriteMethodHeader (Method method, string layoutClass) { var returnType = GetCSharpType (method.ReturnType); @@ -45,7 +45,7 @@ private void WriteMethodHeader (Method method, string initBases) Write (")\n"); if (method.IsConstructor) - WriteLine (initBases); + WriteLine (layoutClass); else WriteLine ("{"); @@ -152,206 +152,200 @@ private bool IsByVal (CppType t) var wrapper = Class.Name; var iface = "I" + Class.Name; var layout = "_" + Class.Name; - - var initBases = "{"; - if (hasBase) { - initBases = "\t: base (impl.TypeInfo) {"; - foreach (var nonPrimaryBase in Class.BaseClasses.Skip (1)) { - initBases = string.Format ("{0}\n\t\t\tnew {1} (impl.TypeInfo);", initBases, nonPrimaryBase.Name); - } - } + var layoutClass = (hasBase? "\t: base (impl.TypeInfo)\n\t\t{" : "{") + "\n\t\t\tLayoutClass ();"; + var initBases = (Class.BaseClasses.Count > 1 ? "\tInitBases ();\n\t\t}" : "}"); #line default #line hidden - #line 20 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 14 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write("// -------------------------------------------------------------------------\n// Managed wrapper for "); #line default #line hidden - #line 21 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 15 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(this.ToStringHelper.ToStringWithCulture( Class.Name )); #line default #line hidden - #line 21 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 15 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write("\n// Generated from "); #line default #line hidden - #line 22 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 16 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(this.ToStringHelper.ToStringWithCulture( Path.GetFileName (Generator.InputFileName) )); #line default #line hidden - #line 22 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 16 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(" on "); #line default #line hidden - #line 22 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 16 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(this.ToStringHelper.ToStringWithCulture( DateTime.Now )); #line default #line hidden - #line 22 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 16 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write("\n//\n// This file was auto generated. Do not edit.\n// -------------------------------------------------------------------------\n\nusing System;\nusing Mono.VisualC.Interop;\n\nnamespace "); #line default #line hidden - #line 30 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 24 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(this.ToStringHelper.ToStringWithCulture( Generator.Namespace )); #line default #line hidden - #line 30 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 24 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(" {\n\n\tpublic partial class "); #line default #line hidden - #line 32 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 26 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(this.ToStringHelper.ToStringWithCulture( wrapper )); #line default #line hidden - #line 32 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 26 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(" : "); #line default #line hidden - #line 32 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 26 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(this.ToStringHelper.ToStringWithCulture( GetBaseString () )); #line default #line hidden - #line 32 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 26 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(" {\n\n\t\tprivate static readonly "); #line default #line hidden - #line 34 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 28 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(this.ToStringHelper.ToStringWithCulture( iface )); #line default #line hidden - #line 34 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 28 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(" impl = Libs."); #line default #line hidden - #line 34 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 28 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(this.ToStringHelper.ToStringWithCulture( Generator.LibBaseName )); #line default #line hidden - #line 34 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 28 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(".GetClass<"); #line default #line hidden - #line 34 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 28 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(this.ToStringHelper.ToStringWithCulture( iface + "," + layout + "," + wrapper )); #line default #line hidden - #line 34 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 28 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write("> (\""); #line default #line hidden - #line 34 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 28 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(this.ToStringHelper.ToStringWithCulture( Class.Name )); #line default #line hidden - #line 34 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 28 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write("\");\n"); #line default #line hidden - #line 35 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 29 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" if (!hasBase) { #line default #line hidden - #line 36 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 30 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write("\t\tpublic CppInstancePtr Native { get; protected set; }\n"); #line default #line hidden - #line 37 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 31 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" } #line default #line hidden - #line 38 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 32 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write("\n"); #line default #line hidden - #line 39 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 33 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" /* Interface */ #line default #line hidden - #line 40 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 34 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write("\t\tpublic interface "); #line default #line hidden - #line 40 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 34 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(this.ToStringHelper.ToStringWithCulture( iface )); #line default #line hidden - #line 40 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 34 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(" : ICppClassOverridable<"); #line default #line hidden - #line 40 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 34 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(this.ToStringHelper.ToStringWithCulture( wrapper )); #line default #line hidden - #line 40 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 34 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write("> {\n"); #line default #line hidden - #line 41 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 35 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" PushIndent ("\t\t\t"); foreach (var method in Class.Methods) { Write (CurrentIndent); @@ -393,91 +387,91 @@ private bool IsByVal (CppType t) #line default #line hidden - #line 78 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 72 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write("\t\t}\n"); #line default #line hidden - #line 79 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 73 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" /* Native layout */ #line default #line hidden - #line 80 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 74 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write("\t\tprivate struct "); #line default #line hidden - #line 80 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 74 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(this.ToStringHelper.ToStringWithCulture( layout )); #line default #line hidden - #line 80 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 74 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(" {\n"); #line default #line hidden - #line 81 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 75 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" foreach (var field in Class.Fields) { #line default #line hidden - #line 82 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 76 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write("\t\t\tpublic "); #line default #line hidden - #line 82 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 76 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(this.ToStringHelper.ToStringWithCulture( GetCSharpType (field.Type) )); #line default #line hidden - #line 82 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 76 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(" "); #line default #line hidden - #line 82 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 76 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(this.ToStringHelper.ToStringWithCulture( field.Name )); #line default #line hidden - #line 82 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 76 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(";\n"); #line default #line hidden - #line 83 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 77 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" } #line default #line hidden - #line 84 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 78 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write("\t\t}\n\n"); #line default #line hidden - #line 86 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 80 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" /* Native fields */ #line default #line hidden - #line 87 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 81 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" PushIndent ("\t\t"); foreach (var field in Class.Fields.Where (f => f.Access != Access.@private)) { WriteLine ("{0} {1} {2} {{", field.Access, GetCSharpType (field.Type), field.Name); @@ -485,132 +479,155 @@ private bool IsByVal (CppType t) #line default #line hidden - #line 90 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 84 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write("\t\t\tget {\n\t\t\t\treturn impl."); #line default #line hidden - #line 91 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 85 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(this.ToStringHelper.ToStringWithCulture( field.Name )); #line default #line hidden - #line 91 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 85 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(" [Native];\n\t\t\t}\n\t\t\tset {\n\t\t\t\timpl."); #line default #line hidden - #line 94 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 88 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(this.ToStringHelper.ToStringWithCulture( field.Name )); #line default #line hidden - #line 94 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 88 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(" [Native] = value;\n\t\t\t}\n\t\t}\n"); #line default #line hidden - #line 97 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - } - ClearIndent(); + #line 91 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + } ClearIndent(); #line default #line hidden - #line 99 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 92 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write("\n"); #line default #line hidden - #line 100 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - /* Native constructor */ + #line 93 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + /* Subclass constructor */ #line default #line hidden - #line 101 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 94 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write("\t\tpublic "); #line default #line hidden - #line 101 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 94 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(this.ToStringHelper.ToStringWithCulture( wrapper )); #line default #line hidden - #line 101 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - this.Write(" (CppInstancePtr native)\n\t\t"); + #line 94 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write(" (CppTypeInfo subClass)\n\t\t"); + + #line default + #line hidden + + #line 95 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write(this.ToStringHelper.ToStringWithCulture( layoutClass )); #line default #line hidden - #line 102 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 95 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write("\n\t\t\tsubClass.AddBase (impl.TypeInfo);\n\t\t"); + + #line default + #line hidden + + #line 97 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(this.ToStringHelper.ToStringWithCulture( initBases )); #line default #line hidden - #line 102 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - this.Write("\n\t\t\tNative = native;\n\t\t}\n\n"); + #line 97 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write("\n\n"); #line default #line hidden - #line 106 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - /* Subclass constructor */ + #line 99 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + /* Native constructor */ #line default #line hidden - #line 107 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 100 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write("\t\tpublic "); #line default #line hidden - #line 107 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 100 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(this.ToStringHelper.ToStringWithCulture( wrapper )); #line default #line hidden - #line 107 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - this.Write(" (CppTypeInfo subClass)\n\t\t"); + #line 100 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write(" (CppInstancePtr native)\n\t\t"); #line default #line hidden - #line 108 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 101 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write(this.ToStringHelper.ToStringWithCulture( layoutClass )); + + #line default + #line hidden + + #line 101 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write("\n\t\t\tNative = native;\n\t\t"); + + #line default + #line hidden + + #line 103 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(this.ToStringHelper.ToStringWithCulture( initBases )); #line default #line hidden - #line 108 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - this.Write("\n\t\t\tsubClass.AddBase (impl.TypeInfo);\n\t\t}\n\n"); + #line 103 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write("\n\n"); #line default #line hidden - #line 112 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 105 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" /* Wrapper methods */ #line default #line hidden - #line 113 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 106 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" PushIndent ("\t\t"); foreach (var method in Class.Methods.Where (m => m.GenWrapperMethod)) { - WriteMethodHeader (method, initBases); + WriteMethodHeader (method, layoutClass); if (method.IsConstructor) Write ("Native = "); @@ -626,27 +643,32 @@ private bool IsByVal (CppType t) } WriteParameters (method.Parameters, false, false); + Write (");\n"); PopIndent (); - Write (");\n{0}}}\n\n", CurrentIndent); + + if (method.IsConstructor) + WriteLine (initBases); + else + WriteLine ("}"); } ClearIndent (); #line default #line hidden - #line 136 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 134 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write("\n"); #line default #line hidden - #line 137 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 135 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" /* Wrapper properties */ #line default #line hidden - #line 138 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 136 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" PushIndent ("\t\t"); foreach (var prop in Class.Properties) { var type = GetCSharpType (prop.Type); @@ -694,173 +716,170 @@ private bool IsByVal (CppType t) #line default #line hidden - #line 181 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - this.Write("\n"); + #line 179 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write("\n\t\tpublic "); #line default #line hidden - #line 182 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - /* Make this wrapper castable to non-primary bases */ -foreach (var npBase in Class.BaseClasses.Skip (1)) { - var prop = npBase.Name; - var field = prop + "_lazy"; - + #line 180 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write(this.ToStringHelper.ToStringWithCulture( hasBase? "override" : "virtual" )); #line default #line hidden - #line 187 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - this.Write("\t\t// Non-primary base class implementation for "); + #line 180 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write(" void Dispose ()\n\t\t{\n"); #line default #line hidden - #line 187 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - this.Write(this.ToStringHelper.ToStringWithCulture( npBase.Name )); + #line 182 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + if (Class.Methods.Any (m => m.IsDestructor && !m.IsArtificial)) { #line default #line hidden - #line 187 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - this.Write(":\n\t\tprivate "); + #line 183 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write("\t\t\timpl.Destruct (Native);\n"); #line default #line hidden - #line 188 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - this.Write(this.ToStringHelper.ToStringWithCulture( npBase.Name )); + #line 184 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + } #line default #line hidden - #line 188 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - this.Write(" "); + #line 185 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write("\t\t\tNative.Dispose ();\n\t\t}\n\n\t\tprivate void LayoutClass ()\n\t\t{\n"); #line default #line hidden - #line 188 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - this.Write(this.ToStringHelper.ToStringWithCulture( field )); + #line 190 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + foreach (var npBase in Class.BaseClasses.Skip (1)) { #line default #line hidden - #line 188 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - this.Write(";\n\t\tpublic "); + #line 191 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write("\t\t\tnew "); #line default #line hidden - #line 189 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 191 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(this.ToStringHelper.ToStringWithCulture( npBase.Name )); #line default #line hidden - #line 189 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - this.Write(" "); + #line 191 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write(" (impl.TypeInfo);\n"); #line default #line hidden - #line 189 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - this.Write(this.ToStringHelper.ToStringWithCulture( prop )); + #line 192 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + } #line default #line hidden - #line 189 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - this.Write(" {\n\t\t\tget {\n\t\t\t\tif ("); + #line 193 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write("\t\t\timpl.TypeInfo.CompleteType ();\n\t\t}\n\n"); #line default #line hidden - #line 191 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - this.Write(this.ToStringHelper.ToStringWithCulture( field )); + #line 196 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + /* Make this wrapper castable to non-primary bases */ +foreach (var npBase in Class.BaseClasses.Skip (1)) { #line default #line hidden - #line 191 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - this.Write(" == null)\n\t\t\t\t\t"); + #line 198 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write("\t\t// Non-primary base class implementation for "); #line default #line hidden - #line 192 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - this.Write(this.ToStringHelper.ToStringWithCulture( field )); + #line 198 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write(this.ToStringHelper.ToStringWithCulture( npBase.Name )); #line default #line hidden - #line 192 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - this.Write(" = impl.TypeInfo.Cast<"); + #line 198 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write(":\n\t\tpublic "); #line default #line hidden - #line 192 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 199 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(this.ToStringHelper.ToStringWithCulture( npBase.Name )); #line default #line hidden - #line 192 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - this.Write("> (this);\n\t\t\t\treturn "); + #line 199 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write(" "); #line default #line hidden - #line 193 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - this.Write(this.ToStringHelper.ToStringWithCulture( field )); + #line 199 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write(this.ToStringHelper.ToStringWithCulture( npBase.Name )); #line default #line hidden - #line 193 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - this.Write(";\n\t\t\t}\n\t\t}\n\t\tpublic static implicit operator "); + #line 199 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write(" { get; protected set; }\n\t\tpublic static implicit operator "); #line default #line hidden - #line 196 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 200 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(this.ToStringHelper.ToStringWithCulture( npBase.Name )); #line default #line hidden - #line 196 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 200 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write("("); #line default #line hidden - #line 196 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 200 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(this.ToStringHelper.ToStringWithCulture( wrapper )); #line default #line hidden - #line 196 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 200 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(" subClass)\n\t\t{\n\t\t\treturn subClass."); #line default #line hidden - #line 198 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - this.Write(this.ToStringHelper.ToStringWithCulture( prop )); + #line 202 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write(this.ToStringHelper.ToStringWithCulture( npBase.Name )); #line default #line hidden - #line 198 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 202 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" this.Write(";\n\t\t}\n\n"); #line default #line hidden - #line 201 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 205 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" PushIndent ("\t\t"); foreach (var method in npBase.Methods) { // With the exception of virtual methods that have been overridden, these methods must be called @@ -871,56 +890,93 @@ foreach (var npBase in Class.BaseClasses.Skip (1)) { WriteMethodHeader (method, initBases); - Write ("{0}.{1} (", prop, method.FormattedName); + Write ("{0}.{1} (", npBase.Name, method.FormattedName); WriteParameters (method.Parameters, false, false); PopIndent (); Write (");\n{0}}}\n\n", CurrentIndent); } ClearIndent (); -} +} +if (Class.BaseClasses.Count > 1) { #line default #line hidden - #line 219 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - this.Write("\n\t\tpublic "); + #line 224 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write("\t\tprivate void InitBases ()\n\t\t{\n"); #line default #line hidden - #line 220 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - this.Write(this.ToStringHelper.ToStringWithCulture( hasBase? "override" : "virtual" )); + #line 226 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + foreach (var npBase in Class.BaseClasses.Skip (1)) { #line default #line hidden - #line 220 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - this.Write(" void Dispose ()\n\t\t{\n"); + #line 227 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write("\t\t\t"); #line default #line hidden - #line 222 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - if (Class.Methods.Any (m => m.IsDestructor && !m.IsArtificial)) { + #line 227 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write(this.ToStringHelper.ToStringWithCulture( npBase.Name )); #line default #line hidden - #line 223 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - this.Write("\t\t\timpl.Destruct (Native);\n"); + #line 227 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write(" = new "); #line default #line hidden - #line 224 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + #line 227 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write(this.ToStringHelper.ToStringWithCulture( npBase.Name )); + + #line default + #line hidden + + #line 227 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write(" (impl.TypeInfo.Cast (this, typeof ("); + + #line default + #line hidden + + #line 227 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write(this.ToStringHelper.ToStringWithCulture( npBase.Name )); + + #line default + #line hidden + + #line 227 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write(")));\n"); + + #line default + #line hidden + + #line 228 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + } + + #line default + #line hidden + + #line 229 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write("\t\t}\n"); + + #line default + #line hidden + + #line 230 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" } #line default #line hidden - #line 225 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - this.Write("\t\t\tNative.Dispose ();\n\t\t}\n\n\t}\n}\n\n"); + #line 231 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" + this.Write("\t}\n}\n\n"); #line default #line hidden diff --git a/src/generator/Templates/CSharp/CSharpClass.tt b/src/generator/Templates/CSharp/CSharpClass.tt index 0da16193..9826f5f4 100644 --- a/src/generator/Templates/CSharp/CSharpClass.tt +++ b/src/generator/Templates/CSharp/CSharpClass.tt @@ -8,14 +8,8 @@ var wrapper = Class.Name; var iface = "I" + Class.Name; var layout = "_" + Class.Name; - - var initBases = "{"; - if (hasBase) { - initBases = "\t: base (impl.TypeInfo) {"; - foreach (var nonPrimaryBase in Class.BaseClasses.Skip (1)) { - initBases = string.Format ("{0}\n\t\t\tnew {1} (impl.TypeInfo);", initBases, nonPrimaryBase.Name); - } - } + var layoutClass = (hasBase? "\t: base (impl.TypeInfo)\n\t\t{" : "{") + "\n\t\t\tLayoutClass ();"; + var initBases = (Class.BaseClasses.Count > 1 ? "\tInitBases ();\n\t\t}" : "}"); #> // ------------------------------------------------------------------------- // Managed wrapper for <#= Class.Name #> @@ -94,26 +88,25 @@ namespace <#= Generator.Namespace #> { impl.<#= field.Name #> [Native] = value; } } -<# } - ClearIndent(); #> +<# } ClearIndent(); #> + +<# /* Subclass constructor */ #> + public <#= wrapper #> (CppTypeInfo subClass) + <#= layoutClass #> + subClass.AddBase (impl.TypeInfo); + <#= initBases #> <# /* Native constructor */ #> public <#= wrapper #> (CppInstancePtr native) - <#= initBases #> + <#= layoutClass #> Native = native; - } - -<# /* Subclass constructor */ #> - public <#= wrapper #> (CppTypeInfo subClass) <#= initBases #> - subClass.AddBase (impl.TypeInfo); - } <# /* Wrapper methods */ #> <# PushIndent ("\t\t"); foreach (var method in Class.Methods.Where (m => m.GenWrapperMethod)) { - WriteMethodHeader (method, initBases); + WriteMethodHeader (method, layoutClass); if (method.IsConstructor) Write ("Native = "); @@ -129,8 +122,13 @@ namespace <#= Generator.Namespace #> { } WriteParameters (method.Parameters, false, false); + Write (");\n"); PopIndent (); - Write (");\n{0}}}\n\n", CurrentIndent); + + if (method.IsConstructor) + WriteLine (initBases); + else + WriteLine ("}"); } ClearIndent (); #> @@ -179,23 +177,29 @@ namespace <#= Generator.Namespace #> { } ClearIndent (); #> + public <#= hasBase? "override" : "virtual" #> void Dispose () + { +<# if (Class.Methods.Any (m => m.IsDestructor && !m.IsArtificial)) { #> + impl.Destruct (Native); +<# } #> + Native.Dispose (); + } + + private void LayoutClass () + { +<# foreach (var npBase in Class.BaseClasses.Skip (1)) { #> + new <#= npBase.Name #> (impl.TypeInfo); +<# } #> + impl.TypeInfo.CompleteType (); + } + <# /* Make this wrapper castable to non-primary bases */ -foreach (var npBase in Class.BaseClasses.Skip (1)) { - var prop = npBase.Name; - var field = prop + "_lazy"; -#> +foreach (var npBase in Class.BaseClasses.Skip (1)) { #> // Non-primary base class implementation for <#= npBase.Name #>: - private <#= npBase.Name #> <#= field #>; - public <#= npBase.Name #> <#= prop #> { - get { - if (<#= field #> == null) - <#= field #> = impl.TypeInfo.Cast<<#= npBase.Name #>> (this); - return <#= field #>; - } - } + public <#= npBase.Name #> <#= npBase.Name #> { get; protected set; } public static implicit operator <#= npBase.Name #>(<#= wrapper #> subClass) { - return subClass.<#= prop #>; + return subClass.<#= npBase.Name #>; } <# PushIndent ("\t\t"); @@ -208,28 +212,27 @@ foreach (var npBase in Class.BaseClasses.Skip (1)) { WriteMethodHeader (method, initBases); - Write ("{0}.{1} (", prop, method.FormattedName); + Write ("{0}.{1} (", npBase.Name, method.FormattedName); WriteParameters (method.Parameters, false, false); PopIndent (); Write (");\n{0}}}\n\n", CurrentIndent); } ClearIndent (); -} #> - - public <#= hasBase? "override" : "virtual" #> void Dispose () +} +if (Class.BaseClasses.Count > 1) { #> + private void InitBases () { -<# if (Class.Methods.Any (m => m.IsDestructor && !m.IsArtificial)) { #> - impl.Destruct (Native); -<# } #> - Native.Dispose (); +<# foreach (var npBase in Class.BaseClasses.Skip (1)) { #> + <#= npBase.Name #> = new <#= npBase.Name #> (impl.TypeInfo.Cast (this, typeof (<#= npBase.Name #>))); +<# } #> } - +<# } #> } } <#+ -private void WriteMethodHeader (Method method, string initBases) +private void WriteMethodHeader (Method method, string layoutClass) { var returnType = GetCSharpType (method.ReturnType); @@ -253,7 +256,7 @@ private void WriteMethodHeader (Method method, string initBases) Write (")\n"); if (method.IsConstructor) - WriteLine (initBases); + WriteLine (layoutClass); else WriteLine ("{");