Browse Source

Many changes to support generator. Factored CppType creating new CppModifiers class instead of enum with support for template parameters. Generator now almost produces usable code out of the box, including automatic property generation and preliminary support for wrapping templated C++ types in generic managed classes.

git-svn-id: https://mono-soc-2010.googlecode.com/svn/trunk/cppinterop@117 a470b8cb-0e6f-1642-1b45-71e107334c4b
pull/1/head
alexander.corrado 15 years ago
parent
commit
8525dd03c6
  1. 76
      Mono.VisualC.Code/Atoms/Class.cs
  2. 46
      Mono.VisualC.Code/Atoms/Enumeration.cs
  3. 63
      Mono.VisualC.Code/Atoms/Field.cs
  4. 184
      Mono.VisualC.Code/Atoms/Method.cs
  5. 4
      Mono.VisualC.Code/Atoms/Preprocessor.cs
  6. 51
      Mono.VisualC.Code/Atoms/Property.cs
  7. 59
      Mono.VisualC.Code/Atoms/Union.cs
  8. 23
      Mono.VisualC.Code/CodeAtom.cs
  9. 42
      Mono.VisualC.Code/CodeDomExtensions.cs
  10. 4
      Mono.VisualC.Code/CodeUnit.cs
  11. 5
      Mono.VisualC.Code/Mono.VisualC.Code.csproj
  12. 4
      Mono.VisualC.Interop/ABI/Impl/ItaniumTypeInfo.cs
  13. 10
      Mono.VisualC.Interop/ABI/Impl/MsvcAbi.cs
  14. 11
      Mono.VisualC.Interop/ABI/Impl/MsvcTypeInfo.cs
  15. 2
      Mono.VisualC.Interop/AssemblyInfo.cs
  16. 8
      Mono.VisualC.Interop/Attributes.cs
  17. 28
      Mono.VisualC.Interop/CppLibrary.cs
  18. 137
      Mono.VisualC.Interop/CppModifiers.cs
  19. 221
      Mono.VisualC.Interop/CppType.cs
  20. 33
      Mono.VisualC.Interop/CppTypeInfo.cs
  21. 1
      Mono.VisualC.Interop/Mono.VisualC.Interop.csproj
  22. 28
      Mono.VisualC.Interop/Util/IEnumerableTransform.cs
  23. 1
      QtTest/Main.cs
  24. 449
      generator/Main.cs
  25. 27
      generator/class.template
  26. 13
      generator/generator.csproj
  27. 3
      generator/interface.template
  28. 3
      generator/struct.template

76
Mono.VisualC.Code/Atoms/Class.cs

@ -6,6 +6,7 @@ using System.Reflection; @@ -6,6 +6,7 @@ using System.Reflection;
using System.CodeDom;
using Mono.VisualC.Interop;
using Mono.VisualC.Code;
namespace Mono.VisualC.Code.Atoms {
@ -27,40 +28,48 @@ namespace Mono.VisualC.Code.Atoms { @@ -27,40 +28,48 @@ namespace Mono.VisualC.Code.Atoms {
public string StaticCppLibrary { get; set; }
public Definition DefinedAs { get; set; }
public IEnumerable<BaseClass> Bases { get; set; }
public IList<BaseClass> Bases { get; set; }
public IList<string> TemplateArguments { get; set; }
public Class (string name)
{
Name = name;
Bases = Enumerable.Empty<BaseClass> ();
Bases = new List<BaseClass> ();
TemplateArguments = new List<string> ();
}
internal protected override CodeObject InsideCodeNamespace (CodeNamespace ns)
internal protected override object InsideCodeNamespace (CodeNamespace ns)
{
var wrapper = new CodeTypeDeclaration (Name) { TypeAttributes = TypeAttributes.Public };
var wrapper = CreateWrapperClass ();
ns.Types.Add (wrapper);
return wrapper;
}
private CodeTypeDeclaration CreateWrapperClass ()
{
var wrapper = new CodeTypeDeclaration (Name) { TypeAttributes = TypeAttributes.Public };
foreach (var arg in TemplateArguments)
wrapper.TypeParameters.Add (arg);
var iface = CreateInterface ();
var native = CreateNativeLayout ();
var iface = CreateInterface (wrapper);
wrapper.Members.Add (iface);
var native = CreateNativeLayout ();
wrapper.Members.Add (native);
// FIXME: For now, we'll have the managed wrapper extend from the first public base class
string managedBase = Bases.Where (b => b.Access == Access.Public).Select (b => b.Name).FirstOrDefault ();
if (managedBase == null) {
bool hasOverrides = true;
if (managedBase == null) {
managedBase = typeof (ICppObject).Name;
hasOverrides = false;
// Add Native property
var nativeField = new CodeMemberField (typeof (CppInstancePtr), "native_ptr") { Attributes = MemberAttributes.Family };
var nativeField = new CodeMemberField (typeof (CppInstancePtr).Name, "native_ptr") { Attributes = MemberAttributes.Family };
var nativeProperty = new CodeMemberProperty {
Name = "Native",
Type = new CodeTypeReference (typeof (CppInstancePtr)),
Type = new CodeTypeReference (typeof (CppInstancePtr).Name),
HasSet = false,
Attributes = MemberAttributes.Public | MemberAttributes.Final
};
@ -72,26 +81,36 @@ namespace Mono.VisualC.Code.Atoms { @@ -72,26 +81,36 @@ namespace Mono.VisualC.Code.Atoms {
wrapper.BaseTypes.Add (managedBase);
// add static impl field
var implField = new CodeMemberField (iface.Name, "impl") { Attributes = MemberAttributes.Static | MemberAttributes.Private };
var implField = new CodeMemberField (iface.TypeReference (), "impl") { Attributes = MemberAttributes.Static | MemberAttributes.Private };
if (StaticCppLibrary != null) {
CodeTypeReference [] types = new CodeTypeReference [] {
new CodeTypeReference (iface.Name),
new CodeTypeReference (native.Name),
new CodeTypeReference (wrapper.Name)
iface.TypeReference (),
native.TypeReference (),
wrapper.TypeReference ()
};
var getClassMethod = new CodeMethodReferenceExpression (new CodeTypeReferenceExpression (StaticCppLibrary), "GetClass", types);
implField.InitExpression = new CodeMethodInvokeExpression (getClassMethod, new CodePrimitiveExpression (Name));
}
wrapper.Members.Add (implField);
foreach (var atom in Atoms)
atom.Visit (wrapper);
CodeMemberMethod dispose = null;
foreach (var atom in Atoms) {
Method method = atom as Method;
if (method != null && method.IsDestructor)
dispose = (CodeMemberMethod)method.InsideCodeTypeDeclaration (wrapper);
else
atom.Visit (wrapper);
}
if (dispose == null)
wrapper.Members.Add (CreateDestructorlessDispose ());
else if (hasOverrides)
dispose.Attributes |= MemberAttributes.Override;
ns.Types.Add (wrapper);
return wrapper;
}
private CodeTypeDeclaration CreateInterface ()
private CodeTypeDeclaration CreateInterface (CodeTypeDeclaration wrapper)
{
var iface = new CodeTypeDeclaration ("I" + Name) {
TypeAttributes = TypeAttributes.Interface | TypeAttributes.NestedPublic,
@ -99,7 +118,10 @@ namespace Mono.VisualC.Code.Atoms { @@ -99,7 +118,10 @@ namespace Mono.VisualC.Code.Atoms {
IsInterface = true
};
iface.BaseTypes.Add (new CodeTypeReference (typeof (ICppClassOverridable<>).Name, new CodeTypeReference (Name)));
foreach (var arg in TemplateArguments)
iface.TypeParameters.Add (arg);
iface.BaseTypes.Add (new CodeTypeReference (typeof (ICppClassOverridable<>).Name, wrapper.TypeReference ()));
foreach (var atom in Atoms)
atom.Visit (iface);
@ -121,6 +143,22 @@ namespace Mono.VisualC.Code.Atoms { @@ -121,6 +143,22 @@ namespace Mono.VisualC.Code.Atoms {
return native;
}
private CodeMemberMethod CreateDestructorlessDispose ()
{
var dispose = new CodeMemberMethod {
Name = "Dispose",
Attributes = MemberAttributes.Public
};
var warning = new CodeCommentStatement ("FIXME: Check for inline destructor for this class.");
dispose.Statements.Add (warning);
var native = new CodeFieldReferenceExpression (new CodeThisReferenceExpression (), "Native");
dispose.Statements.Add (new CodeMethodInvokeExpression (native, "Dispose"));
return dispose;
}
public override void Write (TextWriter writer)
{
string declarator = (DefinedAs == Definition.Class? "class" : "struct");

46
Mono.VisualC.Code/Atoms/Enumeration.cs

@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
using System;
using System.Linq;
using System.IO;
using System.Reflection;
using System.Collections.Generic;
using System.CodeDom;
namespace Mono.VisualC.Code.Atoms {
public class Enumeration : CodeAtom {
public struct Item {
public string Name;
public int Value;
}
public string Name { get; set; }
public IList<Item> Items { get; set; }
public Enumeration (string name)
{
Name = name;
Items = new List<Item> ();
}
internal protected override object InsideCodeNamespace (CodeNamespace ns)
{
var type = new CodeTypeDeclaration (Name) {
TypeAttributes = TypeAttributes.Public,
IsEnum = true
};
foreach (Item i in Items)
type.Members.Add (new CodeMemberField (typeof (int), i.Name) { InitExpression = new CodePrimitiveExpression (i.Value) });
ns.Types.Add (type);
return type;
}
public override void Write (TextWriter writer)
{
throw new NotImplementedException ();
}
}
}

63
Mono.VisualC.Code/Atoms/Field.cs

@ -0,0 +1,63 @@ @@ -0,0 +1,63 @@
using System;
using System.IO;
using System.CodeDom;
using Mono.VisualC.Interop;
namespace Mono.VisualC.Code.Atoms {
public class Field : CodeAtom {
public string Name { get; set; }
public CppType Type { get; set; }
public Field (string name, CppType type)
{
Name = name;
Type = type;
}
internal protected override object InsideCodeTypeDeclaration (CodeTypeDeclaration decl)
{
// FIXME: eventually this could add CppFields to the interface so they could be
// so they could be accessed as properties in the managed api
if (!decl.IsStruct)
return null;
CodeMemberField field = new CodeMemberField { Name = this.Name };
CodeTypeReference typeRef = TypeReference;
if (typeRef == null) {
field.Comments.Add (new CodeCommentStatement ("FIXME: Unknown type \"" + Type.ToString () + "\" for field \"" + Name + ".\" Assuming IntPtr."));
field.Type = new CodeTypeReference (typeof (IntPtr));
} else
field.Type = typeRef;
decl.Members.Add (field);
return field;
}
public CodeTypeReference TypeReference {
get {
if (Type.ElementType == CppTypes.Typename)
return new CodeTypeReference (Type.ElementTypeName, CodeTypeReferenceOptions.GenericTypeParameter);
if (Type.Modifiers.Contains (CppModifiers.Pointer) || Type.Modifiers.Contains (CppModifiers.Reference))
return new CodeTypeReference (typeof (IntPtr));
// FIXME: Handle arrays (fixed size?)
Type managedType = Type.ToManagedType ();
if (managedType != null)
return new CodeTypeReference (managedType);
return null;
}
}
public override void Write (TextWriter writer)
{
writer.WriteLine ("{0} {1};", Type.ToString (), Name);
}
}
}

184
Mono.VisualC.Code/Atoms/Method.cs

@ -1,4 +1,6 @@ @@ -1,4 +1,6 @@
using System;
using System.Linq;
using System.Text;
using System.IO;
using System.Collections.Generic;
using System.CodeDom;
@ -17,64 +19,180 @@ namespace Mono.VisualC.Code.Atoms { @@ -17,64 +19,180 @@ namespace Mono.VisualC.Code.Atoms {
public Access Access { get; set; }
public bool IsVirtual { get; set; }
public bool IsStatic { get; set; }
public bool IsConst { get; set; }
public bool IsConstructor { get; set; }
public bool IsDestructor { get; set; }
public CppType RetType { get; set; }
public IEnumerable<Parameter> Parameters { get; set; }
public IList<Parameter> Parameters { get; set; }
public Method (string name)
{
Name = name;
Parameters = new List<Parameter> ();
}
internal protected override CodeObject InsideCodeTypeDeclaration (CodeTypeDeclaration decl)
internal protected override object InsideCodeTypeDeclaration (CodeTypeDeclaration decl)
{
CodeMemberMethod method = null;
if (decl.IsClass) {
var method = CreateWrapperMethod ();
decl.Members.Add (method);
return method;
} else if (decl.IsInterface)
decl.Members.Add (CreateInterfaceMethod ());
return null;
}
internal protected override object InsideCodeStatementCollection (CodeStatementCollection stmts)
{
List<CodeExpression> arguments = new List<CodeExpression> ();
if (!IsStatic)
arguments.Add (new CodeFieldReferenceExpression (new CodeThisReferenceExpression (), "Native"));
foreach (var param in Parameters) {
// FIXME: handle typenames
if (param.Type.ElementType != CppTypes.Typename) {
Type managedType = param.Type.ToManagedType ();
if (managedType != null && managedType.IsByRef) {
arguments.Add (new CodeDirectionExpression (FieldDirection.Ref, new CodeArgumentReferenceExpression (param.Name)));
continue;
}
}
arguments.Add (new CodeArgumentReferenceExpression (param.Name));
}
if (decl.IsInterface) {
method = new CodeMemberMethod { Name = this.Name };
Type managedType = RetType.ToManagedType ();
if (managedType != null && managedType.IsByRef)
method.ReturnType = new CodeTypeReference (typeof (IntPtr));
else if (managedType != null && managedType != typeof (ICppObject))
method.ReturnType = new CodeTypeReference (managedType);
else
method.ReturnType = new CodeTypeReference (RetType.ElementTypeName);
// FIXME: Does just specifying the field name work for all code generators?
var impl = new CodeFieldReferenceExpression { FieldName = "impl" };
var invoke = new CodeMethodInvokeExpression (impl, Name, arguments.ToArray ());
if (IsVirtual)
method.CustomAttributes.Add (new CodeAttributeDeclaration ("Virtual"));
if (RetType.Equals (CppTypes.Void))
stmts.Add (invoke);
else
stmts.Add (new CodeMethodReturnStatement (invoke));
return null;
}
private CodeMemberMethod CreateInterfaceMethod ()
{
var method = new CodeMemberMethod {
Name = this.Name,
ReturnType = this.ReturnTypeReference
};
if (IsVirtual) method.CustomAttributes.Add (new CodeAttributeDeclaration ("Virtual"));
if (IsConstructor) method.CustomAttributes.Add (new CodeAttributeDeclaration ("Constructor"));
if (IsDestructor) method.CustomAttributes.Add (new CodeAttributeDeclaration ("Destructor"));
if (IsConst) method.CustomAttributes.Add (new CodeAttributeDeclaration ("Const"));
if (IsStatic)
method.CustomAttributes.Add (new CodeAttributeDeclaration ("Static"));
else
method.Parameters.Add (new CodeParameterDeclarationExpression (typeof (CppInstancePtr).Name, "this"));
AddParameters (method, true);
return method;
}
private CodeMemberMethod CreateWrapperMethod ()
{
CodeMemberMethod method;
if (IsConstructor)
method = new CodeConstructor {
Name = FormattedName,
Attributes = MemberAttributes.Public
};
else if (IsDestructor)
method = new CodeMemberMethod {
Name = "Dispose",
Attributes = MemberAttributes.Public
};
else
method = new CodeMemberMethod {
Name = FormattedName,
Attributes = MemberAttributes.Public,
ReturnType = ReturnTypeReference
};
if (IsStatic)
method.Attributes |= MemberAttributes.Static;
else if (!IsVirtual && !IsDestructor)
// I'm only making methods that are virtual in C++ virtual in managed code.
// I think it is the right thing to do because the consumer of the API might not
// get the intended effect if the managed method is overridden and the native method is not.
method.Attributes |= MemberAttributes.Final;
else if (IsVirtual && !IsDestructor)
method.CustomAttributes.Add (new CodeAttributeDeclaration ("OverrideNative"));
AddParameters (method, false);
return method;
}
if (IsStatic)
method.CustomAttributes.Add (new CodeAttributeDeclaration ("Static"));
else
method.Parameters.Add (new CodeParameterDeclarationExpression (typeof (CppInstancePtr).Name, "this"));
public CodeTypeReference ReturnTypeReference {
get {
CodeTypeReference returnType;
if (RetType.ElementType == CppTypes.Typename)
returnType = new CodeTypeReference (RetType.ElementTypeName, CodeTypeReferenceOptions.GenericTypeParameter);
else {
Type managedType = RetType.ToManagedType ();
if (managedType != null && managedType.IsByRef)
returnType = new CodeTypeReference (typeof (IntPtr));
else if (managedType != null && managedType != typeof (ICppObject))
returnType = new CodeTypeReference (managedType);
else
returnType = RetType.TypeReference ();
}
foreach (var param in Parameters) {
return returnType;
}
}
CodeParameterDeclarationExpression paramDecl;
managedType = param.Type.ToManagedType ();
private void AddParameters (CodeMemberMethod method, bool includeMangleAttribute)
{
foreach (var param in Parameters) {
CodeParameterDeclarationExpression paramDecl;
// BOO work around bug in Codedom dealing with byref types!
if (param.Type.ElementType == CppTypes.Typename)
paramDecl = new CodeParameterDeclarationExpression (param.Type.ElementTypeName, param.Name);
else {
Type managedType = param.Type.ToManagedType ();
if (managedType != null && managedType.IsByRef)
paramDecl = new CodeParameterDeclarationExpression (managedType.GetElementType (), param.Name) { Direction = FieldDirection.Ref };
else if (managedType != null && managedType != typeof (ICppObject))
paramDecl = new CodeParameterDeclarationExpression (managedType, param.Name);
else
paramDecl = new CodeParameterDeclarationExpression (param.Type.ElementTypeName, param.Name);
paramDecl = new CodeParameterDeclarationExpression (param.Type.TypeReference (), param.Name);
}
// FIXME: Only add MangleAs attribute if the managed type chosen would mangle differently by default
if (!IsVirtual)
paramDecl.CustomAttributes.Add (new CodeAttributeDeclaration ("MangleAs", new CodeAttributeArgument (new CodePrimitiveExpression (param.Type.ToString ()))));
// FIXME: Only add MangleAs attribute if the managed type chosen would mangle differently by default
string paramStr = param.Type.ToString ();
if (includeMangleAttribute && !IsVirtual && !paramStr.Equals (string.Empty))
paramDecl.CustomAttributes.Add (new CodeAttributeDeclaration ("MangleAs", new CodeAttributeArgument (new CodePrimitiveExpression (paramStr))));
method.Parameters.Add (paramDecl);
}
method.Parameters.Add (paramDecl);
}
}
// FIXME: add wrapper method
if (method != null)
decl.Members.Add (method);
return method;
public string FormattedName {
get {
string upper = Name.ToUpper ();
StringBuilder sb = new StringBuilder (Name.Length);
for (int i = 0; i < Name.Length; i++) {
if (i == 0)
sb.Append (upper [0]);
else if (Name [i] == '_')
sb.Append (upper [++i]);
else
sb.Append (Name [i]);
}
return sb.ToString ();
}
}
public override void Write (TextWriter writer)

4
Mono.VisualC.Code/Atoms/Preprocessor.cs

@ -29,7 +29,7 @@ namespace Mono.VisualC.Code.Atoms { @@ -29,7 +29,7 @@ namespace Mono.VisualC.Code.Atoms {
writer.WriteLine ("#define {0}", Name);
}
internal protected override CodeObject InsideCodeNamespace (CodeNamespace ns)
internal protected override object InsideCodeNamespace (CodeNamespace ns)
{
if (!value_set)
return null;
@ -46,7 +46,7 @@ namespace Mono.VisualC.Code.Atoms { @@ -46,7 +46,7 @@ namespace Mono.VisualC.Code.Atoms {
return constants;
}
internal protected override CodeObject InsideCodeTypeDeclaration (CodeTypeDeclaration decl)
internal protected override object InsideCodeTypeDeclaration (CodeTypeDeclaration decl)
{
if (!value_set)
return null;

51
Mono.VisualC.Code/Atoms/Property.cs

@ -0,0 +1,51 @@ @@ -0,0 +1,51 @@
using System;
using System.IO;
using System.CodeDom;
namespace Mono.VisualC.Code.Atoms {
public class Property : CodeAtom {
public string Name { get; set; }
public Method Getter { get; set; }
public Method Setter { get; set; }
public Property (string name)
{
Name = name;
}
internal protected override object InsideCodeTypeDeclaration (CodeTypeDeclaration decl)
{
// if getter is omitted, just output the setter like a method
if (decl.IsInterface || Getter == null) {
if (Getter != null)
Getter.Visit (decl);
if (Setter != null)
Setter.Visit (decl);
return null;
} else if (!decl.IsClass)
return null;
var prop = new CodeMemberProperty {
Name = this.Name,
// FIXME: For now, no properties will be virtual... change this at some point?
Attributes = MemberAttributes.Public | MemberAttributes.Final,
Type = Getter.ReturnTypeReference
};
Getter.Visit (prop.GetStatements);
if (Setter != null)
Setter.Visit (prop.SetStatements);
decl.Members.Add (prop);
return prop;
}
public override void Write (TextWriter writer)
{
throw new NotImplementedException ();
}
}
}

59
Mono.VisualC.Code/Atoms/Union.cs

@ -0,0 +1,59 @@ @@ -0,0 +1,59 @@
using System;
using System.IO;
using System.CodeDom;
using System.Reflection;
using System.Runtime.InteropServices;
namespace Mono.VisualC.Code.Atoms {
public class Union : CodeContainer {
public string Name { get; set; }
public Union (string name)
{
Name = name;
}
public CodeTypeDeclaration CreateUnionType ()
{
var union = new CodeTypeDeclaration (Name) {
Attributes = MemberAttributes.Public,
TypeAttributes = TypeAttributes.Public | TypeAttributes.ExplicitLayout,
IsStruct = true
};
foreach (var atom in Atoms) {
Field field = atom as Field;
if (field == null)
throw new Exception ("Only Fields allowed in Union.");
CodeMemberField cmf = field.InsideCodeTypeDeclaration (union) as CodeMemberField;
if (cmf != null)
cmf.CustomAttributes.Add (new CodeAttributeDeclaration (new CodeTypeReference (typeof (FieldOffsetAttribute)), new CodeAttributeArgument (new CodePrimitiveExpression (0))));
}
return union;
}
internal protected override object InsideCodeNamespace (CodeNamespace ns)
{
ns.Types.Add (CreateUnionType ());
return null;
}
internal protected override object InsideCodeTypeDeclaration (CodeTypeDeclaration decl)
{
decl.Members.Add (CreateUnionType ());
return null;
}
public override void Write (TextWriter writer)
{
writer.WriteLine ("union {0} {{", Name);
base.Write (writer);
writer.WriteLine ("}");
}
}
}

23
Mono.VisualC.Code/CodeAtom.cs

@ -9,34 +9,39 @@ namespace Mono.VisualC.Code { @@ -9,34 +9,39 @@ namespace Mono.VisualC.Code {
public abstract class CodeAtom {
internal protected virtual void Visit (CodeObject obj)
internal protected virtual void Visit (object obj)
{
CodeObject result = obj;
object result = obj;
while (result != null) {
if (result is CodeCompileUnit) { result = InsideCodeCompileUnit (result as CodeCompileUnit); continue; }
if (result is CodeNamespace) { result = InsideCodeNamespace (result as CodeNamespace); continue; }
if (result is CodeTypeDeclaration) { result = InsideCodeTypeDeclaration (result as CodeTypeDeclaration); continue; }
if (result is CodeCompileUnit) { result = InsideCodeCompileUnit (result as CodeCompileUnit); continue; }
if (result is CodeNamespace) { result = InsideCodeNamespace (result as CodeNamespace); continue; }
if (result is CodeTypeDeclaration) { result = InsideCodeTypeDeclaration (result as CodeTypeDeclaration); continue; }
if (result is CodeMemberMethod) { result = InsideCodeStatementCollection (((CodeMemberMethod)result).Statements); continue; }
if (result is CodeStatementCollection) { result = InsideCodeStatementCollection (result as CodeStatementCollection); continue; }
break;
}
}
internal protected virtual CodeObject InsideCodeCompileUnit (CodeCompileUnit ccu)
internal protected virtual object InsideCodeCompileUnit (CodeCompileUnit ccu)
{
return null;
}
internal protected virtual CodeObject InsideCodeNamespace (CodeNamespace ns)
internal protected virtual object InsideCodeNamespace (CodeNamespace ns)
{
return null;
}
internal protected virtual CodeObject InsideCodeTypeDeclaration (CodeTypeDeclaration decl)
internal protected virtual object InsideCodeTypeDeclaration (CodeTypeDeclaration decl)
{
return null;
}
internal protected virtual object InsideCodeStatementCollection (CodeStatementCollection stmts)
{
return null;
}
public abstract void Write (TextWriter writer);
}
}

42
Mono.VisualC.Code/CodeDomExtensions.cs

@ -0,0 +1,42 @@ @@ -0,0 +1,42 @@
using System;
using System.Linq;
using System.Text;
using System.CodeDom;
using Mono.VisualC.Interop;
namespace Mono.VisualC.Code {
public static class CodeDomExtensions {
public static CodeTypeReference TypeReference (this CodeTypeDeclaration ctd)
{
return new CodeTypeReference (ctd.Name, ctd.TypeParameterReferences ());
}
public static CodeTypeReference TypeReference (this CppType t)
{
return t.TypeReference (false);
}
public static CodeTypeReference TypeReference (this CppType t, bool useManagedType)
{
var tempParm = from m in t.Modifiers.OfType<CppModifiers.TemplateModifier> ()
from p in m.Types
select p.TypeReference (true);
Type managedType = useManagedType? t.ToManagedType () : null;
if (managedType == typeof (ICppObject))
managedType = null;
return new CodeTypeReference (managedType.FullName ?? t.ElementTypeName, tempParm.ToArray ());
}
public static CodeTypeReference [] TypeParameterReferences (this CodeTypeDeclaration ctd)
{
return ctd.TypeParameters.Cast<CodeTypeParameter> ().Select (p => new CodeTypeReference (p)).ToArray ();
}
}
}

4
Mono.VisualC.Code/CodeUnit.cs

@ -22,7 +22,7 @@ namespace Mono.VisualC.Code { @@ -22,7 +22,7 @@ namespace Mono.VisualC.Code {
return ccu;
}
internal protected override CodeObject InsideCodeCompileUnit (CodeCompileUnit ccu)
internal protected override object InsideCodeCompileUnit (CodeCompileUnit ccu)
{
CodeNamespace ns = new CodeNamespace (ManagedNamespace);
ns.Imports.Add (new CodeNamespaceImport ("Mono.VisualC.Interop"));
@ -31,7 +31,7 @@ namespace Mono.VisualC.Code { @@ -31,7 +31,7 @@ namespace Mono.VisualC.Code {
return ns;
}
internal protected override CodeObject InsideCodeNamespace (CodeNamespace ns)
internal protected override object InsideCodeNamespace (CodeNamespace ns)
{
foreach (var atom in Atoms)
atom.Visit (ns);

5
Mono.VisualC.Code/Mono.VisualC.Code.csproj

@ -41,6 +41,11 @@ @@ -41,6 +41,11 @@
<Compile Include="CodeUnit.cs" />
<Compile Include="Access.cs" />
<Compile Include="Atoms\Method.cs" />
<Compile Include="Atoms\Enumeration.cs" />
<Compile Include="CodeDomExtensions.cs" />
<Compile Include="Atoms\Property.cs" />
<Compile Include="Atoms\Field.cs" />
<Compile Include="Atoms\Union.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>

4
Mono.VisualC.Interop/ABI/Impl/ItaniumTypeInfo.cs

@ -11,6 +11,7 @@ namespace Mono.VisualC.Interop.ABI { @@ -11,6 +11,7 @@ namespace Mono.VisualC.Interop.ABI {
public ItaniumTypeInfo (ItaniumAbi abi, IEnumerable<MethodInfo> virtualMethods, Type nativeLayout)
: base (abi, virtualMethods, nativeLayout)
{
// Remove all virtual destructors from their declared position in the vtable
for (int i = 0; i < VirtualMethods.Count; i++) {
if (Abi.GetMethodType (VirtualMethods [i]) != MethodType.NativeDtor)
continue;
@ -27,6 +28,9 @@ namespace Mono.VisualC.Interop.ABI { @@ -27,6 +28,9 @@ namespace Mono.VisualC.Interop.ABI {
public override void AddBase (CppTypeInfo baseType)
{
if (TypeComplete)
return;
hasVirtualDtor |= ((ItaniumTypeInfo)baseType).HasVirtualDestructor;
base.AddBase (baseType);
}

10
Mono.VisualC.Interop/ABI/Impl/MsvcAbi.cs

@ -77,9 +77,13 @@ namespace Mono.VisualC.Interop.ABI { @@ -77,9 +77,13 @@ namespace Mono.VisualC.Interop.ABI {
nm.Append (funcModifier);
// FIXME: deal with storage classes for "this" i.e. the "const" in -> int foo () const;
if (!IsStatic (methodInfo))
nm.Append ('A');
// FIXME: deal with other storage classes for "this" i.e. the "volatile" in -> int foo () volatile;
if (!IsStatic (methodInfo)) {
if (IsConst (methodInfo))
nm.Append ('B');
else
nm.Append ('A');
}
switch (GetCallingConvention (methodInfo)) {
case CallingConvention.Cdecl:

11
Mono.VisualC.Interop/ABI/Impl/MsvcTypeInfo.cs

@ -18,13 +18,10 @@ namespace Mono.VisualC.Interop.ABI { @@ -18,13 +18,10 @@ namespace Mono.VisualC.Interop.ABI {
if (TypeComplete)
return;
if (BaseClasses.Count == 0) {
base.AddBase (baseType);
return;
}
BaseClasses.Add (baseType);
field_offset_padding += baseType.NativeSize;
if (BaseClasses.Count == 0)
base.AddBase (baseType, false);
else
base.AddBase (baseType, true);
}
}

2
Mono.VisualC.Interop/AssemblyInfo.cs

@ -30,5 +30,5 @@ using System.Runtime.CompilerServices; @@ -30,5 +30,5 @@ using System.Runtime.CompilerServices;
//[assembly: AssemblyKeyFile("")]
[assembly: CLSCompliant(true)]
// TODO: This will not work if we ever support saving these assemblies
// FIXME: This will not work if we ever support saving these assemblies
[assembly: InternalsVisibleTo("__CppLibraryImplAssembly")]

8
Mono.VisualC.Interop/Attributes.cs

@ -28,6 +28,10 @@ namespace Mono.VisualC.Interop { @@ -28,6 +28,10 @@ namespace Mono.VisualC.Interop {
[AttributeUsage (AttributeTargets.Method)]
public class StaticAttribute : Attribute {}
// used for the const "this" - for example: int value () const;
[AttributeUsage (AttributeTargets.Method)]
public class ConstAttribute : Attribute {}
// FIXME: Will we ever be calling private methods?
[AttributeUsage (AttributeTargets.Method)]
public class PrivateAttribute : Attribute {}
@ -71,6 +75,10 @@ using Mono.VisualC.Interop; @@ -71,6 +75,10 @@ using Mono.VisualC.Interop;
{
return method.IsDefined (typeof (StaticAttribute), false);
}
public virtual bool IsConst (MethodInfo method)
{
return method.IsDefined (typeof (ConstAttribute), false);
}
public virtual bool IsPrivate (MethodInfo method)
{
return method.IsDefined (typeof (PrivateAttribute), false);

28
Mono.VisualC.Interop/CppLibrary.cs

@ -23,8 +23,8 @@ namespace Mono.VisualC.Interop { @@ -23,8 +23,8 @@ namespace Mono.VisualC.Interop {
internal static AssemblyBuilder interopAssembly;
internal static ModuleBuilder interopModule;
private CppAbi abi;
private string name;
public CppAbi Abi { get; private set; }
public string Name { get; private set; }
static CppLibrary ()
{
@ -35,6 +35,18 @@ namespace Mono.VisualC.Interop { @@ -35,6 +35,18 @@ namespace Mono.VisualC.Interop {
interopModule = interopAssembly.DefineDynamicModule (moduleName, moduleName, true);
}
public CppLibrary (string name)
{
if (name == null)
throw new ArgumentNullException ("Name cannot be NULL.");
this.Name = name;
// FIXME: This is where we'd auto detect the ABI
this.Abi = new ItaniumAbi ();
}
public CppLibrary (string name, CppAbi abi)
{
@ -43,16 +55,8 @@ namespace Mono.VisualC.Interop { @@ -43,16 +55,8 @@ namespace Mono.VisualC.Interop {
if (abi == null)
throw new ArgumentNullException ("Abi cannot be NULL.");
this.name = name;
this.abi = abi;
}
public string Name {
get { return name; }
}
public CppAbi Abi {
get { return abi; }
this.Name = name;
this.Abi = abi;
}
// Mainly for debugging at this point

137
Mono.VisualC.Interop/CppModifiers.cs

@ -0,0 +1,137 @@ @@ -0,0 +1,137 @@
//
// Mono.VisualC.Interop.CppModifiers.cs: Abstracts a C++ type modifiers
//
// Author:
// Alexander Corrado (alexander.corrado@gmail.com)
//
// Copyright (C) 2010 Alexander Corrado
//
using System;
using System.Linq;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace Mono.VisualC.Interop {
public abstract class CppModifiers {
// This can be added to at runtime to support other modifiers
public static readonly Dictionary<string,Func<Match,CppModifiers>> Tokenize = new Dictionary<string,Func<Match,CppModifiers>> () {
{ "\\bconst\\b", m => CppModifiers.Const },
{ "\\*", m => CppModifiers.Pointer },
{ "\\[([^\\]]*)\\]", m => m.Groups [1].Success && m.Groups [1].Value.Trim () != ""? new ArrayModifier (int.Parse (m.Groups [1].Value)) : CppModifiers.Array },
{ "\\&", m => CppModifiers.Reference },
{ "\\bvolatile\\b", m => CppModifiers.Volatile },
{ "\\bsigned\\b", m => CppModifiers.Signed },
{ "\\bunsigned\\b", m => CppModifiers.Unsigned },
{ "\\bshort\\b", m => CppModifiers.Short },
{ "\\blong\\b", m => CppModifiers.Long },
{ "\\<(.*)\\>", m => m.Groups [1].Success && m.Groups [1].Value.Trim () != ""? new TemplateModifier (m.Groups [1].Value) : CppModifiers.Template }
};
public static IEnumerable<CppModifiers> Parse (string input)
{
foreach (var token in Tokenize) {
foreach (Match match in Regex.Matches (input, token.Key))
yield return token.Value (match);
}
}
public static string Remove (string input)
{
foreach (var token in Tokenize)
input = Regex.Replace (input, token.Key, "");
return input;
}
public override bool Equals (object obj)
{
if (obj == null)
return false;
return GetType ().Equals (obj.GetType ());
}
public override int GetHashCode ()
{
return GetType ().GetHashCode ();
}
public static bool operator == (CppModifiers a, CppModifiers b)
{
if (a != null && b != null)
return a.Equals (b);
if (a == null && b == null)
return true;
return false;
}
public static bool operator != (CppModifiers a, CppModifiers b)
{
return !(a == b);
}
public static readonly CppModifiers Const = new ConstModifier ();
public static readonly CppModifiers Pointer = new PointerModifier ();
public static readonly CppModifiers Array = new ArrayModifier ();
public static readonly CppModifiers Reference = new ReferenceModifier ();
public static readonly CppModifiers Volatile = new VolatileModifier ();
public static readonly CppModifiers Signed = new SignedModifier ();
public static readonly CppModifiers Unsigned = new UnsignedModifier ();
public static readonly CppModifiers Short = new ShortModifier ();
public static readonly CppModifiers Long = new LongModifier ();
public static readonly CppModifiers Template = new TemplateModifier ();
// Add list of modifiers here:
public class ConstModifier : CppModifiers { public override string ToString () { return "const"; } }
public class PointerModifier : CppModifiers { public override string ToString () { return "*"; } }
public class ReferenceModifier : CppModifiers { public override string ToString () { return "&"; } }
public class VolatileModifier : CppModifiers { public override string ToString () { return "volatile"; } }
public class SignedModifier : CppModifiers { public override string ToString () { return "signed"; } }
public class UnsignedModifier : CppModifiers { public override string ToString () { return "unsigned"; } }
public class ShortModifier : CppModifiers { public override string ToString () { return "short"; } }
public class LongModifier : CppModifiers { public override string ToString () { return "long"; } }
public class ArrayModifier : CppModifiers {
public int? Size { get; set; }
public ArrayModifier ()
{
}
public ArrayModifier (int size) {
Size = size;
}
public override string ToString ()
{
return string.Format ("[{0}]", Size.HasValue? Size.ToString () : "");
}
}
public class TemplateModifier : CppModifiers {
public CppType [] Types { get; set; }
public TemplateModifier ()
{
}
public TemplateModifier (string types)
{
Types = Regex.Split (types, "(?<!\\<[^\\>]*),").Select (p => new CppType (p)).ToArray ();
}
public TemplateModifier (CppType [] types)
{
Types = types;
}
public override string ToString ()
{
return string.Format ("<{0}>", Types == null? "" : string.Join (", ", Types.Select (t => t.ToString ()).ToArray ()));
}
}
}
}

221
Mono.VisualC.Interop/CppType.cs

@ -18,18 +18,7 @@ using Mono.VisualC.Interop.Util; @@ -18,18 +18,7 @@ using Mono.VisualC.Interop.Util;
namespace Mono.VisualC.Interop {
public enum CppModifiers {
Const,
Pointer,
Array,
Reference,
Volatile,
// ---
Signed,
Unsigned,
Short,
Long
}
// These can be used anywhere a CppType could be used.
public enum CppTypes {
Unknown,
Class,
@ -41,23 +30,13 @@ namespace Mono.VisualC.Interop { @@ -41,23 +30,13 @@ namespace Mono.VisualC.Interop {
Char,
Int,
Float,
Double
Double,
// for template type parameters
Typename
}
public struct CppType {
public static Dictionary<string,CppModifiers> Tokenize = new Dictionary<string, CppModifiers> () {
{ "\\*", CppModifiers.Pointer },
{ "\\[\\s*\\]", CppModifiers.Array },
{ "\\&", CppModifiers.Reference }
};
public static Dictionary<CppModifiers,string> Stringify = new Dictionary<CppModifiers, string> () {
{ CppModifiers.Pointer, "*" },
{ CppModifiers.Array, "[]" },
{ CppModifiers.Reference, "&" }
};
// FIXME: Passing these as delegates allows for the flexibility of doing processing on the
// type (i.e. to correctly mangle the function pointer arguments if the managed type is a delegate),
// however this does not make it very easy to override the default mappings at runtime.
@ -73,15 +52,18 @@ namespace Mono.VisualC.Interop { @@ -73,15 +52,18 @@ namespace Mono.VisualC.Interop {
// single pointer to char gets string
(t) => t.ElementType == CppTypes.Char && t.Modifiers.Count (m => m == CppModifiers.Pointer) == 1? typeof (string) : null,
// pointer to pointer to char gets StringBuilder
(t) => t.ElementType == CppTypes.Char && t.Modifiers.Count (m => m == CppModifiers.Pointer) == 2? typeof (StringBuilder) : null,
// pointer to pointer to char gets string[]
(t) => t.ElementType == CppTypes.Char && t.Modifiers.Count (m => m == CppModifiers.Pointer) == 2? typeof (string).MakeArrayType () : null,
// arrays
(t) => t.Modifiers.Contains (CppModifiers.Array)? t.Subtract (CppModifiers.Array).ToManagedType ().MakeArrayType () : null,
// convert single pointers to primatives to managed byref
(t) => t.Modifiers.Count (m => m == CppModifiers.Pointer) == 1? t.WithoutModifier (CppModifiers.Pointer).ToManagedType ().MakeByRefType () : null,
(t) => t.Modifiers.Count (m => m == CppModifiers.Pointer) == 1? t.Subtract (CppModifiers.Pointer).ToManagedType ().MakeByRefType () : null,
// more than one level of indirection gets IntPtr type
(t) => t.Modifiers.Contains (CppModifiers.Pointer)? typeof (IntPtr) : null,
(t) => t.Modifiers.Contains (CppModifiers.Reference)? t.WithoutModifier (CppModifiers.Reference).ToManagedType ().MakeByRefType () : null,
(t) => t.Modifiers.Contains (CppModifiers.Reference)? t.Subtract (CppModifiers.Reference).ToManagedType ().MakeByRefType () : null,
(t) => t.ElementType == CppTypes.Int && t.Modifiers.Contains (CppModifiers.Short) && t.Modifiers.Contains (CppModifiers.Unsigned)? typeof (ushort) : null,
(t) => t.ElementType == CppTypes.Int && t.Modifiers.Contains (CppModifiers.Long) && t.Modifiers.Contains (CppModifiers.Unsigned)? typeof (ulong) : null,
@ -143,6 +125,8 @@ namespace Mono.VisualC.Interop { @@ -143,6 +125,8 @@ namespace Mono.VisualC.Interop {
// this will contain the name of said type
public string ElementTypeName { get; set; }
// this is initialized lazily to avoid unnecessary heap
// allocations if possible
private List<CppModifiers> internalModifiers;
public List<CppModifiers> Modifiers {
get {
@ -156,7 +140,7 @@ namespace Mono.VisualC.Interop { @@ -156,7 +140,7 @@ namespace Mono.VisualC.Interop {
// here, you can pass in things like "const char*" or "const Foo * const"
// DISCLAIMER: this is really just for convenience for now, and is not meant to be able
// to parse even moderately complex C++ type declarations.
public CppType (string type) : this (Regex.Split (type, "\\s+(?!\\])"))
public CppType (string type) : this (Regex.Split (type, "\\s+(?![^\\>]*\\>|[^\\[\\]]*\\])"))
{
}
@ -168,67 +152,55 @@ namespace Mono.VisualC.Interop { @@ -168,67 +152,55 @@ namespace Mono.VisualC.Interop {
Parse (cppTypeSpec);
}
private void Parse (object [] modifiers)
private void Parse (object [] parts)
{
for (int i = 0; i < modifiers.Length; i++) {
foreach (object part in parts) {
if (modifiers [i] is CppModifiers) {
Modifiers.Add ((CppModifiers)modifiers [i]);
if (part is CppModifiers) {
Modifiers.Add ((CppModifiers)part);
continue;
}
string strModifier = modifiers [i] as string;
if (strModifier != null) {
// FIXME: Use Enum.TryParse here if we decide to make this NET_4_0 only
try {
Modifiers.Add ((CppModifiers)Enum.Parse (typeof (CppModifiers), strModifier, true));
continue;
} catch { }
if (part is CppModifiers []) {
Modifiers.AddRange ((CppModifiers [])part);
continue;
}
// must be a type name
ParseType (modifiers [i]);
}
}
private void ParseType (object type)
{
if (type is CppTypes) {
ElementType = (CppTypes)type;
ElementTypeName = null;
return;
}
string strType = type as string;
if (strType != null) {
// strip tokens off type name
foreach (var token in Tokenize) {
foreach (var match in Regex.Matches (strType, token.Key))
Modifiers.Add (token.Value);
strType = Regex.Replace (strType, token.Key, string.Empty);
if (part is CppTypes) {
ElementType = (CppTypes)part;
continue;
}
// FIXME: Use Enum.TryParse here if we decide to make this NET_4_0 only
try {
CppTypes parsed = (CppTypes)Enum.Parse (typeof (CppTypes), strType, true);
ElementType = parsed;
ElementTypeName = null;
return;
} catch { }
// it's the element type name
strType = strType.Trim ();
if (!strType.Equals (string.Empty))
ElementTypeName = strType;
return;
}
Type managedType = part as Type;
if (managedType != null) {
CppType mapped = CppType.ForManagedType (managedType);
ApplyTo (mapped);
continue;
}
Type managedType = type as Type;
if (managedType != null) {
CppType mapped = CppType.ForManagedType (managedType);
ApplyTo (mapped);
return;
string strPart = part as string;
if (strPart != null) {
var parsed = CppModifiers.Parse (strPart);
if (parsed.Any ()) {
Modifiers.AddRange (parsed);
strPart = CppModifiers.Remove (strPart);
}
// if we have something left, it must be a type name
strPart = strPart.Trim ();
if (strPart != "") {
// FIXME: Use Enum.TryParse here if we decide to make this NET_4_0 only
try {
CppTypes cppTypes = (CppTypes)Enum.Parse (typeof (CppTypes), strPart, true);
ElementType = cppTypes;
continue;
} catch { }
// otherwise it is the element type name...
ElementTypeName = strPart;
}
}
}
}
@ -242,7 +214,7 @@ namespace Mono.VisualC.Interop { @@ -242,7 +214,7 @@ namespace Mono.VisualC.Interop {
ElementTypeName = type.ElementTypeName;
List<CppModifiers> oldModifiers = internalModifiers;
internalModifiers = type.Modifiers;
internalModifiers = type.internalModifiers;
if (oldModifiers != null)
Modifiers.AddRange (oldModifiers);
@ -250,33 +222,54 @@ namespace Mono.VisualC.Interop { @@ -250,33 +222,54 @@ namespace Mono.VisualC.Interop {
return this;
}
// Removes the modifiers from the passed instance from this instance
// Removes the modifiers on the passed instance from this instance
public CppType Subtract (CppType type)
{
if (internalModifiers == null)
return this;
foreach (var modifier in type.Modifiers) {
for (int i = 0; i < internalModifiers.Count; i++) {
if (internalModifiers [i] == modifier)
internalModifiers.RemoveAt (i--);
}
}
CppType current = this;
foreach (var modifier in ((IEnumerable<CppModifiers>)type.Modifiers).Reverse ())
current = current.Subtract (modifier);
return this;
return current;
}
public CppType Subtract (CppModifiers modifier)
{
CppType newType = this;
newType.internalModifiers = new List<CppModifiers> (((IEnumerable<CppModifiers>)newType.Modifiers).Reverse ().WithoutFirst (modifier));
return newType;
}
// note: this adds modifiers "backwards" (it is mainly used by the generator)
public CppType Modify (CppModifiers modifier)
{
CppType newType = this;
var newModifier = new CppModifiers [] { modifier };
if (newType.internalModifiers != null)
newType.internalModifiers.AddFirst (newModifier);
else
newType.internalModifiers = new List<CppModifiers> (newModifier);
return newType;
}
public override bool Equals (object obj)
{
if (obj == null)
return false;
if (obj.GetType () != typeof(CppType))
if (obj.GetType () == typeof (CppTypes))
return Equals (new CppType (obj));
if (obj.GetType () != typeof (CppType))
return false;
CppType other = (CppType)obj;
// FIXME: the order of some modifiers is not significant
return ((internalModifiers == null && other.internalModifiers == null) ||
internalModifiers.SequenceEqual (other.internalModifiers)) &&
return (((internalModifiers == null || !internalModifiers.Any ()) &&
(other.internalModifiers == null || !other.internalModifiers.Any ())) ||
(internalModifiers != null && other.internalModifiers != null &&
internalModifiers.SequenceEqual (other.internalModifiers))) &&
ElementType == other.ElementType &&
ElementTypeName == other.ElementTypeName;
}
@ -291,23 +284,27 @@ namespace Mono.VisualC.Interop { @@ -291,23 +284,27 @@ namespace Mono.VisualC.Interop {
}
}
public override string ToString ()
{
StringBuilder cppTypeString = new StringBuilder ();
if (ElementType != CppTypes.Unknown)
if (ElementType != CppTypes.Unknown && ElementType != CppTypes.Typename)
cppTypeString.Append (Enum.GetName (typeof (CppTypes), ElementType).ToLower ());
if (ElementTypeName != null)
cppTypeString.Append (" ").Append (ElementTypeName);
if (ElementTypeName != null && ElementType != CppTypes.Typename) {
if (cppTypeString.Length > 0)
cppTypeString.Append (' ');
cppTypeString.Append (ElementTypeName);
}
foreach (var modifier in Modifiers) {
string stringified;
if (!Stringify.TryGetValue (modifier, out stringified))
stringified = Enum.GetName (typeof (CppModifiers), modifier).ToLower ();
if (internalModifiers != null) {
foreach (var modifier in internalModifiers) {
string stringified = modifier.ToString ();
cppTypeString.Append (" ").Append (stringified);
if (cppTypeString.Length > 0)
cppTypeString.Append (' ');
cppTypeString.Append (stringified);
}
}
return cppTypeString.ToString ();
@ -323,26 +320,6 @@ namespace Mono.VisualC.Interop { @@ -323,26 +320,6 @@ namespace Mono.VisualC.Interop {
return mappedType;
}
public CppType Modify (CppModifiers modifier)
{
CppType newType = this;
var newModifier = new CppModifiers [] { modifier };
if (newType.internalModifiers != null)
newType.internalModifiers.AddFirst (newModifier);
else
newType.internalModifiers = new List<CppModifiers> (newModifier);
return newType;
}
public CppType WithoutModifier (CppModifiers modifier)
{
CppType newType = this;
newType.internalModifiers = new List<CppModifiers> (newType.Modifiers.Without (modifier));
return newType;
}
public static CppType ForManagedType (Type type)
{

33
Mono.VisualC.Interop/CppTypeInfo.cs

@ -67,17 +67,29 @@ namespace Mono.VisualC.Interop { @@ -67,17 +67,29 @@ namespace Mono.VisualC.Interop {
if (TypeComplete)
return;
BaseClasses.Add (baseType);
int newVirtualMethodCount = baseType.VirtualMethods.Count;
// by default, do not add another vtable pointer for this new base class
AddBase (baseType, false);
}
for (int i = 0; i < newVirtualMethodCount; i++)
VirtualMethods.Insert (BaseVTableSlots + i, baseType.VirtualMethods [i]);
protected virtual void AddBase (CppTypeInfo baseType, bool addVTablePointer)
{
BaseClasses.Add (baseType);
BaseVTableSlots += newVirtualMethodCount;
VTableDelegateTypes.Skew (newVirtualMethodCount);
VTableOverrides.Skew (newVirtualMethodCount);
if (!addVTablePointer) {
// If we're not adding a vtptr, 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 newVirtualMethodCount = baseType.VirtualMethods.Count;
for (int i = 0; i < newVirtualMethodCount; i++)
VirtualMethods.Insert (BaseVTableSlots + i, baseType.VirtualMethods [i]);
BaseVTableSlots += newVirtualMethodCount;
VTableDelegateTypes.Skew (newVirtualMethodCount);
VTableOverrides.Skew (newVirtualMethodCount);
}
field_offset_padding += Marshal.SizeOf (baseType.NativeLayout) + baseType.field_offset_padding;
field_offset_padding += baseType.native_size +
(addVTablePointer? baseType.FieldOffsetPadding : baseType.field_offset_padding);
}
public int CountBases (Func<CppTypeInfo, bool> predicate)
@ -90,9 +102,12 @@ namespace Mono.VisualC.Interop { @@ -90,9 +102,12 @@ namespace Mono.VisualC.Interop {
return count;
}
// FIXME: Make this thread safe?
public virtual void CompleteType ()
{
if (TypeComplete) return;
if (TypeComplete)
return;
foreach (var baseClass in BaseClasses)
baseClass.CompleteType ();

1
Mono.VisualC.Interop/Mono.VisualC.Interop.csproj

@ -57,6 +57,7 @@ @@ -57,6 +57,7 @@
<Compile Include="Util\ReflectionHelper.cs" />
<Compile Include="ABI\Impl\MsvcTypeInfo.cs" />
<Compile Include="Util\MethodSignature.cs" />
<Compile Include="CppModifiers.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>

28
Mono.VisualC.Interop/Util/IEnumerableTransform.cs

@ -103,12 +103,38 @@ namespace Mono.VisualC.Interop.Util { @@ -103,12 +103,38 @@ namespace Mono.VisualC.Interop.Util {
yield return additionalValue;
}
public static bool StartsWith<T> (this IEnumerable<T> current, IEnumerable<T> beginning)
{
IEnumerator<T> currentEnum = current.GetEnumerator ();
IEnumerator<T> beginEnum = beginning.GetEnumerator ();
while (currentEnum.MoveNext ()) {
if (!beginEnum.MoveNext ())
return true;
if (!currentEnum.Current.Equals (beginEnum.Current))
return false;
}
return !beginEnum.MoveNext ();
}
public static IEnumerable<T> Without<T> (this IEnumerable<T> current, T unwantedValue)
{
foreach (var output in current)
foreach (var output in current) {
if (!output.Equals (unwantedValue))
yield return output;
}
}
public static IEnumerable<T> WithoutFirst<T> (this IEnumerable<T> current, T unwantedValue)
{
bool first = true;
foreach (var output in current) {
if (first && output.Equals (unwantedValue))
first = false;
else
yield return output;
}
}
public static int SequenceHashCode<T> (this IEnumerable<T> sequence)

1
QtTest/Main.cs

@ -7,7 +7,6 @@ namespace QtTest { @@ -7,7 +7,6 @@ namespace QtTest {
class MainClass {
public static void Main (string[] args)
{
//System.Diagnostics.Debug.Assert(false, "Whao");
using (QApplication app = new QApplication ()) {
using (QPushButton hello = new QPushButton ("Hello world!"),
hello2 = new QPushButton ("Another button")) {

449
generator/Main.cs

@ -10,9 +10,12 @@ using System.Collections.Generic; @@ -10,9 +10,12 @@ using System.Collections.Generic;
using System.Linq;
using Mono.VisualC.Interop;
using Mono.VisualC.Interop.Util;
using Mono.VisualC.Code;
using Mono.VisualC.Code.Atoms;
using System.Reflection;
using System.CodeDom;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
@ -22,12 +25,33 @@ namespace CPPInterop { @@ -22,12 +25,33 @@ namespace CPPInterop {
public static readonly string [] genericTypeArgs = new string [] { "T", "U", "V", "W", "X", "Y", "Z" };
public string Source { get; set; }
private CodeUnit currentUnit;
public Dictionary<string, string> Classes;
private CodeUnit enumerations;
public HashSet<string> Enumerations;
private CodeUnit unions;
public HashSet<string> Unions;
public string Dir {get; set;}
string templateClass;
string templateStruct;
string templateInterface;
private string nspace;
public string Namespace {
get { return nspace; }
set {
nspace = value;
enumerations.ManagedNamespace = value;
unions.ManagedNamespace = value;
}
}
public string Library {get; set;}
public CodeDomProvider Provider { get; set; }
public CodeGeneratorOptions Options { get; set; }
private Dictionary<string,Property> properties;
public static void Main (string[] args)
{
@ -36,7 +60,10 @@ namespace CPPInterop { @@ -36,7 +60,10 @@ namespace CPPInterop {
var p = new OptionSet () {
{ "h|?|help", v => help = v != null },
{ "f=", v => gen.Source = v },
{ "o=", v => gen.Dir = v }
{ "o=", v => gen.Dir = v },
{ "ns=", v => gen.Namespace = v },
{ "lib=", v => gen.Library = v },
{ "lang=", v => gen.Provider = CodeDomProvider.CreateProvider (v) }
};
List<string> extra = null;
@ -47,6 +74,11 @@ namespace CPPInterop { @@ -47,6 +74,11 @@ namespace CPPInterop {
return;
}
if (help) {
p.WriteOptionDescriptions (Console.Error);
return;
}
if (gen.Source == null) {
Console.Error.WriteLine ("-f required");
return;
@ -56,74 +88,53 @@ namespace CPPInterop { @@ -56,74 +88,53 @@ namespace CPPInterop {
gen.Dir = "output";
Directory.CreateDirectory (gen.Dir);
if (gen.Namespace == null)
gen.Namespace = "Wrappers";
if (gen.Library == null)
gen.Library = "Lib";
if (gen.Library.EndsWith (".dll") || gen.Library.EndsWith (".so") || gen.Library.EndsWith (".dylib"))
gen.Library = gen.Library.Substring (0, gen.Library.LastIndexOf ('.'));
if (gen.Provider == null)
gen.Provider = new CSharpCodeProvider ();
gen.Options = new CodeGeneratorOptions () {
BlankLinesBetweenMembers = false
};
gen.Run ();
}
public Generator ()
{
Classes = new Dictionary<string, string>();
templateClass = File.ReadAllText ("class.template");
templateStruct = File.ReadAllText ("struct.template");
templateInterface = File.ReadAllText ("interface.template");
}
XmlNode find (XmlNode root, XmlAttribute att)
{
if (att != null)
return find (root, att.Value);
return null;
}
Enumerations = new HashSet<string> ();
enumerations = new CodeUnit { ManagedNamespace = Namespace };
XmlNode find (XmlNode root, string id)
{
XmlNode n = root.SelectSingleNode ("/GCC_XML/*[@id='" + id + "']");
//if (n.Name == "Typedef")
// return n;
if (n.Attributes["type"] != null)
return find (root, n.Attributes["type"].Value);
return n;
}
Unions = new HashSet<string> ();
unions = new CodeUnit { ManagedNamespace = Namespace };
CppType findType (XmlNode root, string id)
{
return findType (root, id, new CppType ());
properties = new Dictionary<string, Property> ();
}
CppType findType (XmlNode root, string id, CppType modifiers)
public void Run ()
{
XmlNode n = root.SelectSingleNode ("/GCC_XML/*[@id='" + id + "']");
switch (n.Name) {
case "ArrayType": return findType (root, n.Attributes ["type"].Value, modifiers.Modify (CppModifiers.Array));
case "PointerType": return findType (root, n.Attributes ["type"].Value, modifiers.Modify (CppModifiers.Pointer));
case "ReferenceType": return findType (root, n.Attributes ["type"].Value, modifiers.Modify (CppModifiers.Reference));
case "CvQualifiedType": return findType (root, n.Attributes ["type"].Value, modifiers.Modify (n.Attributes ["const"].Value == "1"? CppModifiers.Const : CppModifiers.Volatile));
case "Typedef": return findType (root, n.Attributes ["type"].Value, modifiers);
case "FundamentalType": return modifiers.ApplyTo (new CppType (n.Attributes ["name"].Value));
case "Class": return modifiers.ApplyTo (new CppType (CppTypes.Class, n.Attributes ["name"].Value));
case "Struct": return modifiers.ApplyTo (new CppType (CppTypes.Struct, n.Attributes ["name"].Value));
case "Enumeration": return modifiers.ApplyTo (new CppType (CppTypes.Enum, n.Attributes ["name"].Value));
XmlDocument xmldoc = new XmlDocument ();
xmldoc.Load (Source);
//XmlNodeList namespaces = xmldoc.SelectNodes ("/GCC_XML/Namespace[@name != '::' and @name != '' and @name != 'std']");
// FIXME: support function pointers better
case "FunctionType": return modifiers.ApplyTo (CppTypes.Void);
}
ProcessClasses (xmldoc);
GenerateStaticLibField ();
throw new NotImplementedException ("Unknown type node: " + n.Name);
SaveFile (enumerations.WrapperToCodeDom (), "Enums");
SaveFile (unions.WrapperToCodeDom (), "Unions");
}
public void Run ()
void ProcessClasses (XmlDocument xmldoc)
{
var csharp = new CSharpCodeProvider ();
var options = new CodeGeneratorOptions {
BlankLinesBetweenMembers = false
};
XmlDocument xmldoc = new XmlDocument ();
xmldoc.Load (Source);
XmlNodeList namespaces = xmldoc.SelectNodes ("/GCC_XML/Namespace[@name != '::' and @name != '' and @name != 'std']");
XmlNodeList classes = xmldoc.SelectNodes ("/GCC_XML/Class[not(@incomplete)]");
foreach (XmlNode clas in classes) {
var f = xmldoc.SelectSingleNode ("/GCC_XML/File[@id='" + clas.Attributes["file"].Value + "']/@name");
if (f != null && f.Value.StartsWith ("/"))
@ -149,62 +160,80 @@ namespace CPPInterop { @@ -149,62 +160,80 @@ namespace CPPInterop {
ras [i] = string.Format ("{0} with {1}", replaceArgs [i].ToString (), letters [i]);
}
Console.WriteLine ("Warning: Creating generic type {0}<{1}> from the instantiated template {2} by replacing {3} (very buggy!!!)", baseName, string.Join (",", letters), name, string.Join (", ", ras));
Console.Error.WriteLine ("Warning: Creating generic type {0}<{1}> from the instantiated template {2} by replacing {3} (very buggy!!!)", baseName, string.Join (",", letters), name, string.Join (", ", ras));
name = baseName;
}
var cu = new CodeUnit { ManagedNamespace = "Qt.Core" };
var classAtom = new Class (name) { StaticCppLibrary = "Qt.Libs.QtCore" };
if (replaceArgs != null)
currentUnit = new CodeUnit { ManagedNamespace = Namespace };
var classAtom = new Class (name) {
StaticCppLibrary = string.Format ("{0}.Libs.{1}", Namespace, Library)
};
if (replaceArgs != null) {
for (int i = 0; i < replaceArgs.Length; i++)
classAtom.TemplateArguments.Add (genericTypeArgs [i]);
cu.Atoms.AddLast (classAtom);
}
currentUnit.Atoms.AddLast (classAtom);
foreach (XmlNode baseNode in clas.SelectNodes ("Base")) {
classAtom.Bases.Add (new Class.BaseClass {
Name = find (xmldoc.DocumentElement, baseNode.Attributes ["type"]).Attributes ["name"].Value,
Access = baseNode.Attributes ["access"].Value == "public"? Access.Public :
baseNode.Attributes ["access"].Value == "protected"? Access.Protected :
Access.Private,
IsVirtual = baseNode.Attributes ["virtual"].Value == "1"
});
}
string size = clas.Attributes["size"].Value;
string members = clas.Attributes["members"].Value;
//string size = clas.Attributes["size"].Value;
var members = clas.Attributes["members"].Value.Split (' ').Where (id => !id.Equals (string.Empty));
//StringBuilder str = new StringBuilder();
foreach (string id in members.Split(new char[]{' '})) {
if (id.Equals (String.Empty))
continue;
XmlNode n = find (xmldoc.DocumentElement, id);
foreach (string id in members) {
XmlNode n = xmldoc.SelectSingleNode ("/GCC_XML/*[@id='" + id + "']");
bool ctor = false;
bool dtor = false;
int fieldCount = 0;
switch (n.Name) {
case "Method":
case "Constructor":
ctor = true;
break;
case "Destructor":
dtor = true;
break;
default:
case "Method":
break;
case "Field":
CppType fieldType = findType (xmldoc.DocumentElement, n.Attributes["type"]);
string fname = "field" + fieldCount++;
if (n.Attributes ["name"] != null && n.Attributes ["name"].Value != "")
fname = n.Attributes ["name"].Value;
classAtom.Atoms.AddLast (new Field (fname, fieldType));
continue;
default:
continue;
}
if (n.Attributes["access"] == null || n.Attributes["access"].Value != "public")
if (n.Attributes["access"] == null || n.Attributes["access"].Value != "public" ||
(n.Attributes["overrides"] != null && n.Attributes["overrides"].Value != "" && !dtor) ||
n.Attributes["extern"] == null || n.Attributes["extern"].Value != "1")
continue;
//str.Append ("\t\t\t");
string mname = n.Attributes["name"].Value;
CppType retType = findType (xmldoc.DocumentElement, n.Attributes["returns"].Value);
if (replaceArgs != null)
CppType retType = findType (xmldoc.DocumentElement, n.Attributes["returns"]);
if (replaceArgs != null) {
for (int i = 0; i < replaceArgs.Length; i++)
if (replaceArgs [i].ElementTypeName == retType.ElementTypeName) {
retType.Subtract (replaceArgs [i]);
retType.ElementTypeName = genericTypeArgs [i];
}
bool virt = n.Attributes["virtual"] != null && n.Attributes["virtual"].Value == "1";
bool stat = n.Attributes["static"] != null && n.Attributes["static"].Value == "1";
//if (virt)
//str.Append ("[Virtual] ");
//str.Append (rett + " " + mname + " (CppInstancePtr @this");
retType = replaceType (retType, replaceArgs [i], genericTypeArgs [i]);
}
List<Method.Parameter> args = new List<Method.Parameter> ();
var methodAtom = new Method (mname) {
var methodAtom = new Method (dtor? "Destruct" : mname) {
RetType = retType,
IsVirtual = virt,
IsStatic = stat,
Parameters = args
IsVirtual = n.Attributes["virtual"] != null && n.Attributes["virtual"].Value == "1",
IsStatic = n.Attributes["static"] != null && n.Attributes["static"].Value == "1",
IsConst = n.Attributes["const"] != null && n.Attributes["const"].Value == "1",
IsConstructor = ctor,
IsDestructor = dtor
};
int c = 0;
@ -216,50 +245,230 @@ namespace CPPInterop { @@ -216,50 +245,230 @@ namespace CPPInterop {
argname = arg.Attributes["name"].Value;
CppType argtype = findType (xmldoc.DocumentElement, arg.Attributes["type"].Value);
if (replaceArgs != null)
if (replaceArgs != null) {
for (int i = 0; i < replaceArgs.Length; i++)
if (replaceArgs [i].ElementTypeName == argtype.ElementTypeName) {
argtype.Subtract (replaceArgs [i]);
argtype.ElementTypeName = genericTypeArgs [i];
}
argtype = replaceType (argtype, replaceArgs [i], genericTypeArgs [i]);
}
//str.Append (", " + argtype + " " + argname);
args.Add (new Method.Parameter { Name = argname, Type = argtype });
methodAtom.Parameters.Add (new Method.Parameter { Name = argname, Type = argtype });
// tee hee
c++;
}
//str.AppendLine (");");
// if it's const, returns a value, and has no parameters, assume it's a property getter (for now?)
if (methodAtom.IsConst && !retType.Equals (CppTypes.Void) && !methodAtom.Parameters.Any ()) {
var pname = methodAtom.FormattedName;
Property propertyAtom;
if (properties.TryGetValue (pname, out propertyAtom)) {
propertyAtom.Getter = methodAtom;
} else {
propertyAtom = new Property (pname) { Getter = methodAtom };
properties.Add (pname, propertyAtom);
classAtom.Atoms.AddLast (propertyAtom);
}
continue;
}
// if it's name starts with "set", does not return a value, and has one arg (besides this ptr)
// AND there is a corresponding getter method, then assume it's a property setter
if (mname.ToLower ().StartsWith ("set") && retType.Equals (CppTypes.Void) && methodAtom.Parameters.Count == 1) {
string getterName = "translate(@name, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') = '" +
mname.Substring (3).TrimStart ('_').ToLower () + "'";
string isMember = "@id = '" + string.Join ("' or @id = '", members.ToArray ()) + "'";
string pname = methodAtom.FormattedName.Substring (3);
Property propertyAtom = null;
// FIXME: This xpath is probably very slow if the class has many members
if (properties.TryGetValue (pname, out propertyAtom) ||
xmldoc.SelectSingleNode (string.Format ("/GCC_XML/Method[{0} and ({1})]", getterName, isMember)) != null) {
if (propertyAtom != null) {
propertyAtom.Setter = methodAtom;
} else {
propertyAtom = new Property (pname) { Setter = methodAtom };
properties.Add (pname, propertyAtom);
classAtom.Atoms.AddLast (propertyAtom);
}
// set the method's arg name to "value" so that the prop setter works right
Method.Parameter valueParam = methodAtom.Parameters [0];
valueParam.Name = "value";
methodAtom.Parameters [0] = valueParam;
continue;
}
}
classAtom.Atoms.AddLast (methodAtom);
}
Classes.Add (name, sanitize (name) + ".cs");
FileStream fs = File.Create (Path.Combine (Dir, Classes[name]));
StreamWriter sw = new StreamWriter(fs);
/*
StringBuilder sb = new StringBuilder();
string strstruct = String.Format (templateStruct, name);
string strinterface = String.Format (templateInterface, name, "", str.ToString());
sb.Append (string.Format (templateClass,
"Qt.Core",
name,
"ICppObject",
strinterface,
strstruct,
size));
sw.Write (sb.ToString());
*/
csharp.GenerateCodeFromCompileUnit (cu.WrapperToCodeDom (), sw, options);
sw.Flush ();
sw.Close ();
Classes.Add (name, sanitize (name) + "." + Provider.FileExtension);
SaveFile (currentUnit.WrapperToCodeDom (), name);
}
}
XmlNode find (XmlNode root, XmlAttribute att)
{
if (att != null)
return find (root, att.Value);
return null;
}
XmlNode find (XmlNode root, string id)
{
XmlNode n = root.SelectSingleNode ("/GCC_XML/*[@id='" + id + "']");
//if (n.Name == "Typedef")
// return n;
if (n.Attributes["type"] != null)
return find (root, n.Attributes["type"].Value);
return n;
}
CppType findType (XmlNode root, XmlAttribute att)
{
if (att != null)
return findType (root, att.Value);
return CppTypes.Void;
}
CppType findType (XmlNode root, string id)
{
return findType (root, id, new CppType ());
}
CppType findType (XmlNode root, string id, CppType modifiers)
{
XmlNode n = root.SelectSingleNode ("/GCC_XML/*[@id='" + id + "']");
switch (n.Name) {
case "ArrayType": return findType (root, n.Attributes ["type"].Value, modifiers.Modify (CppModifiers.Array));
case "PointerType": return findType (root, n.Attributes ["type"].Value, modifiers.Modify (CppModifiers.Pointer));
case "ReferenceType": return findType (root, n.Attributes ["type"].Value, modifiers.Modify (CppModifiers.Reference));
case "CvQualifiedType":
return findType (root, n.Attributes ["type"].Value,
modifiers.Modify (n.Attributes ["const"] != null && n.Attributes ["const"].Value == "1"? CppModifiers.Const : CppModifiers.Volatile));
case "Typedef": return findType (root, n.Attributes ["type"].Value, modifiers);
case "FundamentalType": return modifiers.ApplyTo (new CppType (n.Attributes ["name"].Value));
case "Class": return modifiers.ApplyTo (new CppType (CppTypes.Class, n.Attributes ["name"].Value));
case "Struct": return modifiers.ApplyTo (new CppType (CppTypes.Struct, n.Attributes ["name"].Value));
case "Union": return modifiers.ApplyTo (ProcessUnion (root, n));
case "Enumeration": return modifiers.ApplyTo (ProcessEnum (n));
// FIXME: support function pointers betters
case "FunctionType": return modifiers.ApplyTo (CppTypes.Void);
}
throw new NotImplementedException ("Unknown type node: " + n.Name);
}
CppType ProcessEnum (XmlNode enm)
{
bool hasName = false;
string ename = "Enum" + Enumerations.Count;
if (enm.Attributes ["name"] != null && enm.Attributes ["name"].Value != "") {
hasName = true;
ename = enm.Attributes ["name"].Value;
}
if (!hasName || !Enumerations.Contains (ename)) {
Enumeration enumAtom = new Enumeration (enm.Attributes ["name"].Value);
foreach (XmlNode v in enm.SelectNodes ("EnumValue"))
enumAtom.Items.Add (new Enumeration.Item { Name = v.Attributes ["name"].Value, Value = Convert.ToInt32 (v.Attributes ["init"].Value) });
if (hasName) // assume it might be shared between classes
enumerations.Atoms.AddLast (enumAtom);
else
currentUnit.Atoms.AddLast (enumAtom);
Enumerations.Add (ename);
}
return new CppType (CppTypes.Enum, ename);
}
CppType ProcessUnion (XmlNode root, XmlNode union)
{
bool hasName = false;
string uname = "Union" + Unions.Count;
if (union.Attributes ["name"] != null && union.Attributes ["name"].Value != "") {
hasName = true;
uname = union.Attributes ["name"].Value;
}
if (!hasName || !Unions.Contains (uname)) {
Union unionAtom = new Union (uname);
foreach (string id in union.Attributes["members"].Value.Split (' ').Where (id => !id.Equals (string.Empty))) {
XmlNode n = root.SelectSingleNode ("/GCC_XML/*[@id = '" + id + "']");
// FIXME: Support union constructors/destructors?
if (n.Name != "Field")
continue;
Field field = new Field (n.Attributes ["name"].Value, findType (root, n.Attributes ["type"]));
unionAtom.Atoms.AddLast (field);
}
if (hasName) // assume it might be shared between classes
unions.Atoms.AddLast (unionAtom);
else
currentUnit.Atoms.AddLast (unionAtom);
Unions.Add (uname);
}
return new CppType (CppTypes.Union, uname);
}
void GenerateStaticLibField ()
{
var ccu = new CodeCompileUnit ();
var ns = new CodeNamespace (Namespace);
var cls = new CodeTypeDeclaration ("Libs") {
TypeAttributes = TypeAttributes.NotPublic | TypeAttributes.Sealed | TypeAttributes.Class,
IsPartial = true,
IsClass = true
};
var field = new CodeMemberField (typeof (CppLibrary), Library) {
Attributes = MemberAttributes.Public | MemberAttributes.Static,
InitExpression = new CodeObjectCreateExpression (typeof (CppLibrary), new CodePrimitiveExpression (Library))
};
cls.Members.Add (field);
ns.Types.Add (cls);
ccu.Namespaces.Add (ns);
SaveFile (ccu, "Lib_" + Library);
}
void SaveFile (CodeCompileUnit ccu, string baseName)
{
var sw = File.CreateText (Path.Combine (Dir, sanitize (baseName) + "." + Provider.FileExtension));
Provider.GenerateCodeFromCompileUnit (ccu, sw, Options);
sw.Flush ();
sw.Close ();
sw.Dispose ();
}
static CppType replaceType (CppType inType, CppType toReplace, string tn)
{
// FIXME: The order of some modifiers is not significant.. is this a problem?
if (/* inType.ElementType == toReplace.ElementType && */
inType.ElementTypeName == toReplace.ElementTypeName &&
inType.Modifiers.StartsWith (toReplace.Modifiers))
return new CppType (CppTypes.Typename, tn, inType.Modifiers.Skip (toReplace.Modifiers.Count).ToArray ());
foreach (var tempMod in inType.Modifiers.OfType<CppModifiers.TemplateModifier> ())
for (int i = 0; i < tempMod.Types.Length; i++)
tempMod.Types [i] = replaceType (tempMod.Types [i], toReplace, tn);
return inType;
}
static string sanitize (string name)
{

27
generator/class.template

@ -1,27 +0,0 @@ @@ -1,27 +0,0 @@
using System;
using Mono.VisualC.Interop;
namespace {0} {{
public class {1} : {2} {{
// interface
{3}
// struct
{4}
public {1} (IntPtr native) : base (native)
{{
}}
public override int NativeSize {{
get {{ return {5}; }}
}}
public override void Dispose ()
{{
throw new Exception ("This should never be called!");
}}
}}
}}

13
generator/generator.csproj

@ -18,7 +18,7 @@ @@ -18,7 +18,7 @@
<DefineConstants>DEBUG</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Commandlineparameters>-f=/Users/Alex/OpenSource/gccxml/gccxml-build/bin/qobject.xml -o=.</Commandlineparameters>
<Commandlineparameters>-f=/Users/Alex/OpenSource/gccxml/gccxml-build/bin/qapplication.xml -o=.</Commandlineparameters>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
@ -46,17 +46,6 @@ @@ -46,17 +46,6 @@
<Properties InternalTargetFrameworkVersion="3.5" />
</MonoDevelop>
</ProjectExtensions>
<ItemGroup>
<None Include="class.template">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="interface.template">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="struct.template">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Mono.VisualC.Code\Mono.VisualC.Code.csproj">
<Project>{A22BF9D9-BBCB-4462-BE08-0F4D5280B180}</Project>

3
generator/interface.template

@ -1,3 +0,0 @@ @@ -1,3 +0,0 @@
public interface I{0} : ICppClassOverridable<{0}> {1} {{
{2}
}}

3
generator/struct.template

@ -1,3 +0,0 @@ @@ -1,3 +0,0 @@
private struct _{0} {{
public IntPtr d_ptr;
}}
Loading…
Cancel
Save