mirror of https://github.com/mono/CppSharp.git
c-sharpdotnetmonobindingsbridgecclangcpluspluscppsharpglueinteropparserparsingpinvokeswigsyntax-treevisitorsxamarinxamarin-bindings
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
398 lines
13 KiB
398 lines
13 KiB
<#@ template language="C#" inherits="ClassBase" #> |
|
<#@ import namespace="System.IO" #> |
|
<#@ import namespace="System.Linq" #> |
|
<#@ import namespace="System.Collections.Generic" #> |
|
<#@ import namespace="Mono.Cxxi" #> |
|
<# |
|
var hasBase = Class.BaseClasses.Count > 0; |
|
var wrapper = Class.Name; |
|
var iface = "I" + Class.Name; |
|
var layout = "_" + Class.Name; |
|
var layoutClass = (hasBase? "\t: base (impl.TypeInfo)\n\t\t{" : "{") + "\n\t\t\t__cxxi_LayoutClass ();"; |
|
var overrideInitBases = Generator.CheckPrimaryBases (Class, c => c.BaseClasses.Count > 1); |
|
var initBases = ((overrideInitBases || Class.BaseClasses.Count > 1) ? "\t__cxxi_InitBases ();\n\t\t}" : "}"); |
|
var @namespace = Generator.Lib.BaseNamespace + (Class.ParentNamespace != null? "." + string.Join (".", Class.ParentNamespace.FullyQualifiedName) : ""); |
|
|
|
if (!Nested) { |
|
#> |
|
// ------------------------------------------------------------------------- |
|
// Managed wrapper for <#= Class.Name #> |
|
// Generated from <#= Path.GetFileName (Generator.InputFileName) #> on <#= DateTime.Now #> |
|
// |
|
// This file was auto generated. Do not edit. |
|
// ------------------------------------------------------------------------- |
|
|
|
using System; |
|
using Mono.Cxxi; |
|
|
|
namespace <#= @namespace #> { |
|
<# } /* if !Nested */ #> |
|
public partial class <#= wrapper #> : <#= GetBaseString () #> { |
|
|
|
private static readonly <#= iface #> impl = Libs.<#= Generator.Lib.BaseName #>.GetClass<<#= iface + "," + layout + "," + wrapper #>> ("<#= Class.Name #>"); |
|
<# if (!hasBase) { #> |
|
public CppInstancePtr Native { get; protected set; } |
|
<# } #> |
|
|
|
<# /* Interface */ #> |
|
[MangleAs ("<#= Class.MangleType.ToString () #>")] |
|
public partial interface <#= iface #> : ICppClassOverridable<<#= wrapper #>> { |
|
<# PushIndent ("\t\t\t"); |
|
foreach (var method in Class.Methods) { |
|
Write (CurrentIndent); |
|
|
|
if (method.IsVirtual) Write ("[Virtual] "); |
|
if (method.IsStatic) Write ("[Static] "); |
|
if (method.IsArtificial) Write ("[Artificial] "); |
|
if (method.IsInline) Write ("[Inline] "); |
|
if (method.IsConst) Write ("[Const] "); |
|
if (method.IsConstructor) Write ("[Constructor] "); |
|
if (method.IsDestructor) Write ("[Destructor] "); |
|
if (method.IsCopyCtor) Write ("[CopyConstructor] "); |
|
|
|
if (Generator.IsByVal (method.ReturnType)) { |
|
Write ("[return: ByVal] "); |
|
} |
|
if (method.IsConstructor) |
|
Write ("CppInstancePtr"); |
|
else |
|
Write (CSharpLanguage.TypeName (Generator.CppTypeToManaged (method.ReturnType), Context.Interface | Context.Return)); |
|
Write (" "); |
|
Write (CSharpLanguage.SafeIdentifier (method.Name)); |
|
|
|
Write (" ("); |
|
if (!method.IsStatic) { |
|
Write ("CppInstancePtr @this"); |
|
if (method.Parameters.Count != 0) |
|
Write (", "); |
|
} |
|
|
|
WriteParameters (method.Parameters, true, !method.IsVirtual); |
|
Write (");\n"); |
|
} |
|
foreach (var field in Class.Fields.Where (f => f.Access != Access.@private)) { |
|
WriteLine ("CppField<{0}> {1} {{ get; }}", CSharpLanguage.TypeName (Generator.CppTypeToManaged (field.Type), Context.Interface | Context.Generic), CSharpLanguage.SafeIdentifier (field.Name)); |
|
} |
|
PopIndent (); #> |
|
} |
|
<# /* Native layout */ #> |
|
public unsafe struct <#= layout #> { |
|
<# PushIndent ("\t\t\t"); |
|
foreach (var field in Class.Fields) { |
|
var array = field.Type.Modifiers.OfType<CppModifiers.ArrayModifier> ().SingleOrDefault (); //FIXME: Handle more than one? |
|
if (array != null && array.Size.HasValue) { |
|
var elementType = CSharpLanguage.TypeName (Generator.CppTypeToManaged (field.Type), Context.Generic).TrimEnd ('[',']'); |
|
WriteLine ("public fixed {0} {1} [{2}];", elementType, CSharpLanguage.SafeIdentifier (field.Name), array.Size.Value); |
|
} else { |
|
WriteLine ("public {0} {1};", CSharpLanguage.TypeName (Generator.CppTypeToManaged (field.Type), Context.Generic), CSharpLanguage.SafeIdentifier (field.Name)); |
|
} |
|
} |
|
PopIndent (); #> |
|
} |
|
|
|
<# /* Native fields */ #> |
|
<# PushIndent ("\t\t"); |
|
foreach (var field in Class.Fields.Where (f => f.Access != Access.@private)) { |
|
var fieldName = CSharpLanguage.SafeIdentifier (field.Name); |
|
WriteLine ("{0} {1} {2} {{", field.Access, CSharpLanguage.TypeName (Generator.CppTypeToManaged (field.Type), Context.Wrapper | Context.Return), fieldName); #> |
|
get { |
|
return impl.<#= fieldName #> [Native]; |
|
} |
|
set { |
|
impl.<#= fieldName #> [Native] = value; |
|
} |
|
} |
|
<# } PopIndent(); #> |
|
|
|
<# /* Nested classes */ #> |
|
<# foreach (var klass in Class.NestedClasses) { |
|
var nestedTempl = new CSharpClass { |
|
Generator = this.Generator, |
|
Class = klass, |
|
Nested = true |
|
}; |
|
Write (nestedTempl.TransformText ()); |
|
} #> |
|
|
|
<# /* Nested enums */ #> |
|
<# foreach (var @enum in Class.NestedEnums) { |
|
Generator.EnumTemplate.Generator = Generator; |
|
Generator.EnumTemplate.Enum = @enum; |
|
Generator.EnumTemplate.Nested = true; |
|
Write (Generator.EnumTemplate.TransformText ()); |
|
} #> |
|
|
|
<# /* Subclass constructor */ #> |
|
public <#= wrapper #> (CppTypeInfo subClass) |
|
<#= layoutClass #> |
|
subClass.AddBase (impl.TypeInfo); |
|
} |
|
|
|
<# /* Native constructor */ #> |
|
public <#= wrapper #> (CppInstancePtr native) |
|
<#= layoutClass #> |
|
Native = native; |
|
<#= initBases #> |
|
|
|
<# /* Wrapper methods */ #> |
|
<# PushIndent ("\t\t"); |
|
foreach (var method in Class.Methods.Where (m => m.GenWrapperMethod)) { |
|
var methodName = CSharpLanguage.SafeIdentifier (method.Name); |
|
WriteMethodHeader (method, layoutClass, false, false); |
|
|
|
if (method.IsConstructor) |
|
Write ("Native = "); |
|
|
|
Write ("impl.{0} (", methodName); |
|
if (!method.IsStatic) { |
|
if (method.IsConstructor) |
|
Write ("impl.Alloc (this)"); |
|
else |
|
Write ("Native"); |
|
if (method.Parameters.Count != 0) |
|
Write (", "); |
|
} |
|
|
|
WriteParameters (method.Parameters, false, false); |
|
Write (");\n"); |
|
PopIndent (); |
|
|
|
if (method.IsConstructor) |
|
WriteLine (initBases); |
|
else |
|
WriteLine ("}"); |
|
} |
|
PopIndent (); #> |
|
|
|
<# /* Wrapper properties */ #> |
|
<# PushIndent ("\t\t"); |
|
foreach (var prop in Class.Properties) { |
|
var propName = CSharpLanguage.SafeIdentifier (prop.Name); |
|
var type = CSharpLanguage.TypeName (Generator.CppTypeToManaged (prop.Type), Context.Wrapper | Context.Return); |
|
|
|
Write (CurrentIndent + "public "); |
|
|
|
if ((prop.GetMethod == null || prop.GetMethod.IsVirtual) && |
|
(prop.SetMethod == null || prop.SetMethod.IsVirtual)) |
|
Write ("virtual "); |
|
|
|
Write (type); |
|
Write (" "); |
|
Write (propName); |
|
Write (" {\n"); |
|
|
|
PushIndent ("\t"); |
|
Write (CurrentIndent); |
|
|
|
if (prop.GetMethod != null) { |
|
if (prop.GetMethod.IsVirtual) |
|
Write ("[OverrideNative (\"{0}\")] ", prop.GetMethod.Name); |
|
|
|
Write ("get {\n"); |
|
PushIndent ("\t"); |
|
WriteLine ("return impl.{0} (Native);", prop.GetMethod.Name); |
|
PopIndent (); |
|
WriteLine ("}"); |
|
} |
|
if (prop.SetMethod != null) { |
|
if (prop.SetMethod.IsVirtual) |
|
Write ("[OverrideNative (\"{0}\")] ", prop.SetMethod.Name); |
|
|
|
WriteLine ("set {"); |
|
PushIndent ("\t"); |
|
WriteLine ("impl.{0} (Native, value);", prop.SetMethod.Name); |
|
PopIndent (); |
|
WriteLine ("}"); |
|
} |
|
|
|
PopIndent (); |
|
WriteLine ("}\n"); |
|
} |
|
PopIndent (); #> |
|
|
|
partial void BeforeDestruct (); |
|
partial void AfterDestruct (); |
|
|
|
public <#= hasBase? "override" : "virtual" #> void Dispose () |
|
{ |
|
BeforeDestruct (); |
|
<# if (Class.Methods.Any (m => m.IsDestructor && !m.IsArtificial)) { #> |
|
impl.Destruct (Native); |
|
<# } #> |
|
Native.Dispose (); |
|
AfterDestruct (); |
|
} |
|
|
|
private void __cxxi_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)) { #> |
|
|
|
#region Non-primary base class implementation for <#= npBase.Name #> |
|
private class <#= wrapper + "__" + npBase.Name #> : <#= npBase.Name #> { |
|
public <#= wrapper #> instance; |
|
public <#= wrapper + "__" + npBase.Name #> (<#= wrapper #> instance) |
|
: base (<#= wrapper #>.impl.TypeInfo.Cast (instance, typeof (<#= npBase.Name #>))) |
|
{ |
|
<#= wrapper #>.impl.TypeInfo.InitNonPrimaryBase (this, instance, typeof (<#= npBase.Name #>)); |
|
this.instance = instance; |
|
} |
|
|
|
<# PushIndent ("\t\t\t"); |
|
foreach (var method in npBase.Methods.Where (m => m.IsVirtual)) { |
|
|
|
if (!method.GenWrapperMethod || Class.Methods.Any (m => m.Node.CheckValue ("overrides", method.Node.Id))) |
|
continue; |
|
|
|
/* this is the managed override that has to call the subclass's method */ |
|
WriteMethodHeader (method, null, true, false); |
|
|
|
Write ("instance.{0} (", npBase.Name + "__" + method.FormattedName); |
|
|
|
WriteParameters (method.Parameters, false, false); |
|
PopIndent (); |
|
Write (");\n{0}}}\n\n", CurrentIndent); |
|
|
|
/* this is the method that calls the base implementation that the subclass will use */ |
|
WriteMethodHeader (method, npBase.Name + "__" + method.FormattedName, true, false); |
|
|
|
Write ("base.{0} (", method.FormattedName); |
|
|
|
WriteParameters (method.Parameters, false, false); |
|
PopIndent (); |
|
Write (");\n{0}}}\n\n", CurrentIndent); |
|
} |
|
PopIndent (); #> |
|
} |
|
private <#= wrapper #>__<#= npBase.Name #> __cxxi_<#= npBase.Name #>; |
|
public <#= npBase.Name #> <#= npBase.Name #> { get { return __cxxi_<#= npBase.Name #>; } } |
|
public static implicit operator <#= npBase.Name #>(<#= wrapper #> subClass) |
|
{ |
|
return subClass.<#= npBase.Name #>; |
|
} |
|
public static explicit operator <#= wrapper #>(<#= npBase.Name #> baseClass) |
|
{ |
|
if (baseClass == null) return null; |
|
var obj = baseClass as <#= wrapper + "__" + npBase.Name #>; |
|
if (obj == null) throw new InvalidCastException (); |
|
return obj.instance; |
|
} |
|
|
|
<# /* Add virtual methods of non-primary bases to this class proper so they can be overridden */ #> |
|
<# PushIndent ("\t\t"); |
|
foreach (var method in npBase.Methods.Where (m => m.IsVirtual)) { |
|
|
|
if (!method.GenWrapperMethod || Class.Methods.Any (m => m.Node.CheckValue ("overrides", method.Node.Id))) |
|
continue; |
|
|
|
WriteMethodHeader (method, npBase.Name + "__" + method.FormattedName, true, true); |
|
|
|
Write ("{0}.{1} (", "__cxxi_" + npBase.Name, npBase.Name + "__" + method.FormattedName); |
|
|
|
WriteParameters (method.Parameters, false, false); |
|
PopIndent (); |
|
Write (");\n{0}}}\n\n", CurrentIndent); |
|
} |
|
PopIndent (); |
|
WriteLine ("#endregion"); |
|
} |
|
|
|
if (overrideInitBases || Class.BaseClasses.Count > 1) { #> |
|
protected <#= overrideInitBases ? "override" : "virtual" #> void __cxxi_InitBases () |
|
{ |
|
<#= overrideInitBases? "base.__cxxi_InitBases ();" : "" #> |
|
<# foreach (var npBase in Class.BaseClasses.Skip (1)) { #> |
|
__cxxi_<#= npBase.Name #> = new <#= wrapper + "__" + npBase.Name #> (this); |
|
<# } #> |
|
} |
|
<# } #> |
|
} |
|
<# if (!Nested) { #> |
|
} |
|
<# } #> |
|
|
|
<#+ |
|
private void WriteMethodHeader (Method method, string layoutClass, bool isNonPrimaryOverride, bool @protected) |
|
{ |
|
var returnType = CSharpLanguage.TypeName (Generator.CppTypeToManaged (method.ReturnType), Context.Wrapper | Context.Return); |
|
|
|
if (!isNonPrimaryOverride && method.IsVirtual) |
|
WriteLine ("[OverrideNative (\"{0}\")]", method.Name); |
|
|
|
Write (CurrentIndent + (@protected? "protected" : method.Access.ToString ()) + " "); |
|
if (method.IsConstructor) { |
|
Write (method.FormattedName); |
|
} else { |
|
if (method.IsStatic) Write ("static "); |
|
if (method.IsVirtual && (!isNonPrimaryOverride || layoutClass != null)) Write ("virtual "); |
|
else if (isNonPrimaryOverride) Write ("override "); |
|
// ...? |
|
Write (returnType); |
|
Write (" "); |
|
Write (isNonPrimaryOverride && layoutClass != null? layoutClass : method.FormattedName); |
|
} |
|
|
|
Write (" ("); |
|
WriteParameters (method.Parameters, true, false); |
|
Write (")\n"); |
|
|
|
if (method.IsConstructor && layoutClass != null) |
|
WriteLine (layoutClass); |
|
else |
|
WriteLine ("{"); |
|
|
|
PushIndent ("\t"); |
|
Write (CurrentIndent); |
|
|
|
if (returnType != "void") |
|
Write ("return "); |
|
} |
|
|
|
private void WriteParameters (IList<Parameter> parameters, bool writeType, bool writeAttributes) |
|
{ |
|
for (var i = 0; i < parameters.Count; i++) { |
|
if (i != 0) |
|
Write (", "); |
|
|
|
var type = CSharpLanguage.TypeName (Generator.CppTypeToManaged (parameters [i].Type), Context.Parameter); |
|
|
|
if (writeAttributes) { |
|
var mangleAs = parameters [i].Type.ToString (); |
|
if (mangleAs != "" && mangleAs != type) |
|
Write ("[MangleAs (\"{0}\")] ", mangleAs); |
|
if (Generator.IsByVal (parameters [i].Type)) |
|
Write ("[ByVal] "); |
|
} |
|
|
|
if (writeType) { |
|
Write (type); |
|
Write (" "); |
|
} else { |
|
if (type.StartsWith ("ref ")) |
|
Write ("ref "); |
|
} |
|
|
|
Write (CSharpLanguage.SafeIdentifier (parameters [i].Name)); |
|
} |
|
} |
|
|
|
private string GetBaseString () |
|
{ |
|
if (Class.BaseClasses.Count == 0) |
|
return "ICppObject"; |
|
|
|
var str = Class.BaseClasses [0].Name; |
|
if (Class.BaseClasses.Count > 1) { |
|
str = string.Format ("{0} /*, {1} */", str, string.Join (", ", Class.BaseClasses.Skip (1).Select (bc => bc.Name).ToArray ())); |
|
} |
|
|
|
return str; |
|
} |
|
|
|
#> |