/// <summary> /// If a method returns a type that is marshalled as struct, /// then this is incompatible with C. /// Append an out parameter that will receive the struct. /// </summary> private void CreateStructOutParameters() { foreach (var method in Project.ClassDefinitions.Values.SelectMany(c => c.Methods)) { var type = method.ReturnType; TypeRefDefinition targetType; if (type.Target != null && type.Target.MarshalAsStruct) { targetType = type; } else if (type.Kind == TypeKind.LValueReference && type.Referenced.Target != null && type.Referenced.Target.MarshalAsStruct) { targetType = type.Referenced; } else { continue; } targetType = targetType.Copy(); targetType.IsConst = false; var outType = new TypeRefDefinition { Kind = TypeKind.Pointer, Referenced = targetType }; method.OutValueParameter = new ParameterDefinition("value", outType) { MarshalDirection = MarshalDirection.Out }; } }
void AddForwardReference(List <ManagedClass> forwardRefs, TypeRefDefinition type, HeaderDefinition header) { if (type.IsBasic) { return; } switch (type.Kind) { case TypeKind.Pointer: case TypeKind.LValueReference: AddForwardReference(forwardRefs, type.Referenced, header); return; } var target = type.Target; if (target == null) { return; } if (target.IsExcluded || target.MarshalAsStruct || target.Header == header) { return; } var targetManaged = DotNetParser.GetManaged(target); if (!forwardRefs.Contains(targetManaged)) { forwardRefs.Add(targetManaged); } }
public override bool Equals(object obj) { if (obj == null) { return(false); } TypeRefDefinition t = obj as TypeRefDefinition; if (t == null) { return(false); } if (t.IsBasic != IsBasic || t.IsConstantArray != IsConstantArray || t.IsPointer != IsPointer || t.IsReference != IsReference) { return(false); } if (IsPointer || IsReference || IsConstantArray) { return(t.Referenced.Equals(Referenced)); } if (Name == null) { return(t.Name == null); } return(t.Name.Equals(Name)); }
void AddForwardReference(List <ClassDefinition> forwardRefs, TypeRefDefinition type, HeaderDefinition header) { if (type.IsBasic) { return; } if (type.IsPointer || type.IsReference) { AddForwardReference(forwardRefs, type.Referenced, header); return; } if (type.Target == null) { return; } if (type.Target.IsExcluded || forwardRefs.Contains(type.Target) || PrecompiledHeaderReferences.Contains(type.Target.ManagedName)) { return; } // Forward ref to class in another header if (type.Target.Header != header) { forwardRefs.Add(type.Target); } }
void WriteTypeCS(TypeRefDefinition type) { if (type.IsBasic) { Write(type.ManagedNameCS, WriteTo.CS); } else if (type.HasTemplateTypeParameter) { Write(type.ManagedNameCS, WriteTo.CS); } else if (type.Referenced != null) { if (type.IsPointer && type.Referenced.ManagedNameCS.Equals("void")) // void* { Write("IntPtr", WriteTo.CS); } else { Write(BulletParser.GetTypeNameCS(type), WriteTo.CS); } } else { Write(BulletParser.GetTypeNameCS(type), WriteTo.CS); } }
public static string GetTypeRefName(TypeRefDefinition type) { if (!string.IsNullOrEmpty(type.Name) && type.Name.Equals("btAlignedObjectArray")) { if (type.SpecializedTemplateType != null) { return("Aligned" + type.SpecializedTemplateType.ManagedName + "Array^"); } } switch (type.ManagedName) { case "Matrix3x3": return("Matrix"); case "Transform": return("Matrix"); case "Quaternion": case "Vector3": case "Vector4": return(type.ManagedName); } if (type.ManagedName.Equals("float") && "btScalar".Equals(type.Name)) { return("btScalar"); } return(type.ManagedTypeRefName); }
bool IsCacheableType(TypeRefDefinition t) { if (t.IsBasic) { return(false); } if (t.Target != null) { if (t.Target.IsPureEnum) { return(false); } } if (t.Referenced != null) { return(IsCacheableType(t.Referenced)); } switch (t.Name) { case "btTransform": case "btQuaternion": case "btVector3": case "btVector4": return(false); } return(true); }
public static string GetTypeNameCS(TypeRefDefinition type) { switch (type.ManagedName) { case "Matrix3x3": case "Transform": return("Matrix"); } if (type.IsConstantArray) { switch (type.Referenced.Name) { case "bool": return("BoolArray"); case "int": return("IntArray"); case "unsigned int": return("UIntArray"); case "unsigned short": return("UShortArray"); case "btScalar": return("FloatArray"); case "btVector3": return("Vector3Array"); case "btDbvt": return("DbvtArray"); case "btSoftBody::Body": return("BodyArray"); } if (type.Referenced.Referenced != null) { switch (type.Referenced.Referenced.Name) { case "btDbvtNode": return("DbvtNodePtrArray"); case "btDbvtProxy": return("DbvtProxyPtrArray"); case "btSoftBody::Node": return("NodePtrArray"); } } return(GetTypeNameCS(type.Referenced) + "[]"); } return(type.ManagedNameCS); }
public string GetName(TypeRefDefinition type) { switch (type.Kind) { case TypeKind.Typedef: if (type.Referenced.Kind == TypeKind.Pointer && type.Referenced.Referenced.Kind == TypeKind.FunctionProto) { if (type.Target != null && !type.Target.IsExcluded) { return(GetManaged(type.Target).Name); } break; } else if (type.Referenced.IsBasic) { // TODO: C++/CLI: typedef to basic type can return typedef // TODO: Pinvoke: typedef to basic type returns basic type return(GetName(type.Referenced)); } else { return(GetName(type.Referenced)); } case TypeKind.ConstantArray: case TypeKind.LValueReference: case TypeKind.Pointer: return(GetName(type.Referenced)); case TypeKind.Enum: case TypeKind.Record: case TypeKind.Unexposed: if (type.Target != null && !type.Target.IsExcluded) { return(GetManaged(type.Target).Name); } break; } if (type.IsBasic) { if (type.Name.Equals("unsigned char")) { return("byte"); } return(type.Name); } if (type.HasTemplateTypeParameter) { return(type.Name); } Console.WriteLine("Unresolved reference to " + type.Name); return(type.Name); }
private static string GetTypeNameC(TypeRefDefinition type) { string name = ""; if (type.IsConst) { // Note: basic type can be const if (type.Referenced == null || (type.Referenced != null && !type.Referenced.ConstCanonical)) { name = "const "; } } if (type.IsBasic) { return(name + type.Name); } if (type.Kind == TypeKind.Typedef) { if (type.Referenced.IsBasic) { return(type.Name); } if (type.Referenced.Kind == TypeKind.Pointer && type.Referenced.Referenced.Kind == TypeKind.FunctionProto) { return(type.Name); } return(name + GetTypeNameC(type.Referenced)); } if (type.Referenced != null) { return(name + GetTypeNameC(type.Referenced) + "*"); } var target = type.Target; if (target != null && target is EnumDefinition) { if (target.Parent != null && target.Parent.IsPureEnum) { return(target.Parent.FullName.Replace("::", "_")); } } // Template name to C form if (type.FullName.Contains("<")) { string template = type.FullName.Replace('<', '_').Replace(">", "").Replace(" *", "Ptr"); template = template.Replace(' ', '_'); return(name + template.Replace("::", "_")); } return(name + type.FullName.Replace("::", "_")); }
void ResolveTypeRef(TypeRefDefinition typeRef) { switch (typeRef.Kind) { case TypeKind.Enum: case TypeKind.Record: case TypeKind.Unexposed: if (Project.ClassDefinitions.ContainsKey(typeRef.Name)) { typeRef.Target = Project.ClassDefinitions[typeRef.Name]; return; } Console.WriteLine($"Unresolved reference: {typeRef.Name}"); if (typeRef.TemplateParams != null) { typeRef.TemplateParams.ForEach(ResolveTypeRef); // Create template specialization class string templateName = typeRef.Name.Substring(0, typeRef.Name.IndexOf('<')); ClassDefinition template; if (Project.ClassDefinitions.TryGetValue(templateName, out template)) { if (!template.IsExcluded) { //string name = $"{typeRef.Name}<{typeRef.TemplateParams.First().Name}>"; string name = typeRef.Name; var classTemplate = template as ClassTemplateDefinition; var header = classTemplate.Header; var specializedClass = new ClassDefinition(name, header); specializedClass.BaseClass = template; header.Classes.Add(specializedClass); Project.ClassDefinitions.Add(name, specializedClass); } } } break; case TypeKind.Typedef: var underlying = typeRef.Canonical; if (underlying.Kind == TypeKind.Pointer && underlying.Referenced.Kind == TypeKind.FunctionProto) { typeRef.Target = Project.ClassDefinitions[typeRef.Name]; return; } break; } if (typeRef.Referenced != null) { ResolveTypeRef(typeRef.Referenced); } }
public string GetName(TypeRefDefinition type) { switch (type.Kind) { case TypeKind.Typedef: if (type.Referenced.Kind == TypeKind.Pointer && type.Referenced.Referenced.Kind == TypeKind.FunctionProto) { if (type.Target != null && !type.Target.IsExcluded) { return GetManaged(type.Target).Name; } break; } else if (type.Referenced.IsBasic) { // TODO: C++/CLI: typedef to basic type can return typedef // TODO: Pinvoke: typedef to basic type returns basic type return GetName(type.Referenced); } else { return GetName(type.Referenced); } case TypeKind.ConstantArray: case TypeKind.LValueReference: case TypeKind.Pointer: return GetName(type.Referenced); case TypeKind.Enum: case TypeKind.Record: case TypeKind.Unexposed: if (type.Target != null && !type.Target.IsExcluded) { return GetManaged(type.Target).Name; } break; } if (type.IsBasic) { if (type.Name.Equals("unsigned char")) { return "byte"; } return type.Name; } if (type.HasTemplateTypeParameter) return type.Name; Console.WriteLine("Unresolved reference to " + type.Name); return type.Name; }
void ParseTemplateBaseCursor(Cursor cursor) { var tokens = _context.TranslationUnit.Tokenize(cursor.Extent) .TakeWhile(t => !t.Spelling.Equals("{")) .SkipWhile(t => !t.Spelling.Equals(":")); if (!tokens.Any()) { return; } var baseTokens = tokens.ToList(); int templSpecStart = -1, templSpecEnd = -1; for (int i = 0; i < baseTokens.Count; i++) { var token = baseTokens[i]; if (token.Spelling == "<") { templSpecStart = i; } else if (token.Spelling == ">") { templSpecEnd = i; } } if (templSpecStart != -1 && templSpecEnd != -1) { string template = baseTokens[templSpecStart - 1].Spelling; string templateSpec = string.Join(" ", baseTokens.GetRange(templSpecStart + 1, templSpecEnd - templSpecStart - 1) .Select(t => t.Spelling)); templateSpec = TypeRefDefinition.GetBasicName(templateSpec); string templateName = $"{template}<{templateSpec}>"; ClassDefinition classTemplate; if (!project.ClassDefinitions.TryGetValue(templateName, out classTemplate)) { var classTemplateNew = new ClassTemplateDefinition(template, _context.Header); classTemplateNew.TemplateParameters.Add(templateSpec); var baseTemplate = project.ClassDefinitions.FirstOrDefault(c => c.Value.Name.Equals(template)); classTemplateNew.BaseClass = baseTemplate.Value; project.ClassDefinitions[templateName] = classTemplateNew; _context.Header.Classes.Add(classTemplateNew); classTemplate = classTemplateNew; } _context.Class.BaseClass = classTemplate; } }
// Does the type require additional lines of code to marshal? public static bool TypeRequiresMarshal(TypeRefDefinition type) { switch (type.Kind) { case TypeKind.ConstantArray: case TypeKind.LValueReference: case TypeKind.Pointer: return(TypeRequiresMarshal(type.Referenced)); } return(type.Target != null && type.Target.MarshalAsStruct); }
void ResolveTypeRef(TypeRefDefinition typeRef) { if (typeRef.IsBasic || typeRef.HasTemplateTypeParameter) { return; } if (typeRef.IsPointer || typeRef.IsReference || typeRef.IsConstantArray) { ResolveTypeRef(typeRef.Referenced); } else if (!Project.ClassDefinitions.ContainsKey(typeRef.Name)) { // Search for unscoped enums bool resolvedEnum = false; foreach (var @class in Project.ClassDefinitions.Values.Where(c => c is EnumDefinition)) { if (typeRef.Name.Equals(@class.FullyQualifiedName + "::" + @class.Name)) { typeRef.Target = @class; resolvedEnum = true; } } if (!resolvedEnum) { Console.WriteLine("Class " + typeRef.Name + " not found!"); } } else { typeRef.Target = Project.ClassDefinitions[typeRef.Name]; } if (typeRef.SpecializedTemplateType != null) { ResolveTypeRef(typeRef.SpecializedTemplateType); // Create template specialization class string name = string.Format("{0}<{1}>", typeRef.Name, typeRef.SpecializedTemplateType.Name); if (!Project.ClassDefinitions.ContainsKey(name)) { var templateClass = typeRef.Target; if (templateClass != null && !templateClass.IsExcluded) { var header = templateClass.Header; var specializedClass = new ClassDefinition(name, header); specializedClass.BaseClass = templateClass; header.Classes.Add(specializedClass); Project.ClassDefinitions.Add(name, specializedClass); } } } }
// Return condition unless type is already used under the same condition. string GetTypeConditional(TypeRefDefinition type, HeaderDefinition header) { string typeConditional = GetTypeConditional(type); if (typeConditional != null && headerConditional.ContainsKey(header.ManagedName)) { if (headerConditional[header.ManagedName].Equals(typeConditional)) { return(null); } } return(typeConditional); }
// Return condition unless type is already used under the same condition. private string GetTypeConditional(TypeRefDefinition type, ManagedHeader header) { string typeConditional = GetTypeConditional(type); if (typeConditional != null && headerConditionals.ContainsKey(header.Name)) { if (headerConditionals[header.Name].Equals(typeConditional)) { return(null); } } return(typeConditional); }
private string GetTypeName(TypeRefDefinition type) { if (type.Kind == TypeKind.Typedef) { if (type.Referenced.Kind == TypeKind.Pointer && type.Referenced.Referenced.Kind == TypeKind.FunctionProto) { return(GetName(type)); } if (type.Canonical.IsBasic) { return(type.Name); } return(GetTypeName(type.Referenced)); } if (type.Kind == TypeKind.LValueReference) { return(GetTypeName(type.Referenced)); } if (!string.IsNullOrEmpty(type.Name) && type.Name.Equals("btAlignedObjectArray")) { if (type.TemplateParams != null) { return("Aligned" + GetName(type.TemplateParams[0]) + "Array^"); } } switch (type.Kind) { case TypeKind.Pointer: case TypeKind.LValueReference: case TypeKind.ConstantArray: if (type.Referenced.Kind == TypeKind.Void) { return("IntPtr"); } switch (GetName(type)) { case "char": return("String^"); case "float": return(string.Format("array<{0}>^", type.Referenced.Name)); } return(GetName(type) + '^'); } return(GetName(type)); }
private void CreateFieldGetter(FieldDefinition field, ClassDefinition @class, string getterName, MethodDefinition setter) { MethodDefinition getter; // Use getter with an out parameter for structs if (field.Type.Target != null && field.Type.Target.MarshalAsStruct) { getter = new MethodDefinition(getterName, @class, 1); getter.ReturnType = new TypeRefDefinition("void"); string paramName = setter != null ? setter.Parameters[0].Name : "value"; var paramType = new TypeRefDefinition(field.Type.Name) { Kind = TypeKind.Pointer, Referenced = field.Type.Copy() }; getter.Parameters[0] = new ParameterDefinition(paramName, paramType) { MarshalDirection = MarshalDirection.Out }; } else { TypeRefDefinition type; if (field.Type.Canonical.Kind == TypeKind.Record) { type = new TypeRefDefinition() { Kind = TypeKind.Pointer, Referenced = field.Type.Copy() }; } else if (field.Type.Canonical.Kind == TypeKind.Unexposed) { // TODO: type = field.Type; } else { type = field.Type; } getter = new MethodDefinition(getterName, @class, 0); getter.ReturnType = type; } getter.Field = field; field.Getter = getter; }
// Does the type require additional lines of code to marshal? public static bool TypeRequiresMarshal(TypeRefDefinition type) { switch (type.ManagedName) { case "Matrix3x3": case "Quaternion": case "Transform": case "Vector3": case "Vector4": return(true); default: return(false); } }
public static string GetTypeName(TypeRefDefinition type) { switch (type.ManagedName) { case "Matrix3x3": case "Quaternion": case "Transform": case "Vector3": case "Vector4": return("btScalar"); default: return(type.FullName); } }
private void CreateFieldSetter(FieldDefinition field, ClassDefinition @class, string setterName) { var type = field.Type; var typeCanonical = type.Canonical; // Can't assign value to reference or constant array switch (typeCanonical.Kind) { case TypeKind.LValueReference: case TypeKind.ConstantArray: return; case TypeKind.Record: if (typeCanonical.Target == null) { return; } if (!typeCanonical.Target.MarshalAsStruct) { return; } type = new TypeRefDefinition { IsConst = true, Kind = TypeKind.Pointer, Referenced = type.Copy() }; break; default: type = type.Copy(); break; } var setter = new MethodDefinition(setterName, @class, 1) { Field = field, ReturnType = new TypeRefDefinition("void") }; setter.Parameters[0] = new ParameterDefinition("value", type) { MarshalDirection = MarshalDirection.In }; field.Setter = setter; }
// If the type is defined in a conditionally compiled header, return the condition string. string GetTypeConditional(TypeRefDefinition type) { var target = type.Target; if (target == null && type.Referenced != null) { target = type.Referenced.Target; } if (target != null && headerConditional.ContainsKey(target.Header.ManagedName)) { return(headerConditional[target.Header.ManagedName]); } return(null); }
public TypeRefDefinition Copy() { var t = new TypeRefDefinition { HasTemplateTypeParameter = HasTemplateTypeParameter, IsConst = IsConst, IsIncomplete = IsIncomplete, Name = Name, Referenced = Referenced != null?Referenced.Copy() : null, TemplateParams = TemplateParams?.Select(p => p.Copy()).ToList(), Target = Target, Kind = Kind }; return(t); }
public TypeRefDefinition Copy() { var t = new TypeRefDefinition(); t.HasTemplateTypeParameter = HasTemplateTypeParameter; t.IsBasic = IsBasic; t.IsConst = IsConst; t.IsConstantArray = IsConstantArray; t.IsPointer = IsPointer; t.IsReference = IsReference; t.Name = Name; t.Referenced = Referenced; t.SpecializedTemplateType = SpecializedTemplateType; t.Target = Target; return(t); }
private void CopyTemplateMethods(ClassDefinition thisClass, ClassTemplateDefinition template, Dictionary <string, string> templateParams = null) { if (templateParams == null) { templateParams = new Dictionary <string, string>(); var templateBase = template.BaseClass as ClassTemplateDefinition; for (int i = 0; i < template.TemplateParameters.Count; i++) { string param = templateBase.TemplateParameters[i]; string paramValue = template.TemplateParameters[i]; templateParams[param] = TypeRefDefinition.GetBasicName(paramValue); } CopyTemplateMethods(thisClass, templateBase, templateParams); return; } thisClass.BaseClass = template.BaseClass; var scriptedNameMapping = Project.ClassNameMapping as ScriptedMapping; if (scriptedNameMapping != null) { scriptedNameMapping.Globals.Header = thisClass.Header; } // TODO: //template.ManagedName = Project.ClassNameMapping.Map(template.Name); foreach (var templateClass in template.NestedClasses) { var classSpec = new ClassDefinition(templateClass.Name, thisClass.Header, thisClass); Project.ClassDefinitions.Add(classSpec.FullyQualifiedName, classSpec); foreach (var templateMethod in templateClass.Methods) { SpecializeTemplateMethod(classSpec, templateMethod, templateParams); } } foreach (var templateMethod in template.Methods.Where(m => !m.IsConstructor)) { SpecializeTemplateMethod(thisClass, templateMethod, templateParams); } }
public static string GetTypeGetterCSMarshal(PropertyDefinition prop, int level) { StringBuilder output = new StringBuilder(); TypeRefDefinition type = prop.Type; // If cached property can only be set in constructor, // the getter can simply return the cached value // TODO: check if cached value is initialized in all constructors CachedProperty cachedProperty; if (prop.Parent.CachedProperties.TryGetValue(prop.Name, out cachedProperty)) { if (cachedProperty.Property.Setter == null) { output.AppendLine(GetTabs(level + 2) + string.Format("get {{ return {0}; }}", cachedProperty.CacheFieldName)); return(output.ToString()); } } if (!type.IsBasic) { switch (type.ManagedNameCS) { case "Matrix3x3": case "Quaternion": case "Transform": case "Vector3": case "Vector4": output.AppendLine(GetTabs(level + 2) + "get"); output.AppendLine(GetTabs(level + 2) + "{"); output.AppendLine(GetTabs(level + 3) + GetTypeNameCS(type) + " value;"); output.AppendLine(GetTabs(level + 3) + string.Format("{0}_{1}(_native, out value);", prop.Parent.FullNameCS, prop.Getter.Name)); output.AppendLine(GetTabs(level + 3) + "return value;"); output.AppendLine(GetTabs(level + 2) + '}'); return(output.ToString()); } } output.AppendLine(GetTabs(level + 2) + string.Format("get {{ return {0}{1}_{2}(_native){3}; }}", GetTypeMarshalConstructorStartCS(prop.Getter), prop.Parent.FullNameCS, prop.Getter.Name, GetTypeMarshalConstructorEndCS(prop.Getter))); return(output.ToString()); }
private static string GetTypeSetterCSMarshal(TypeRefDefinition type) { type = type.Canonical; if ((type.Target != null && type.Target.MarshalAsStruct) || (type.Kind == TypeKind.LValueReference && type.Referenced.Target != null && type.Referenced.Target.MarshalAsStruct)) { return("ref value"); } if (!type.IsBasic) { if (type.Kind == TypeKind.Pointer && type.Referenced.Kind == TypeKind.Void) { return("value"); } return("value._native"); } return("value"); }
// Is the struct passed by value or by reference? public static bool MarshalStructByValue(TypeRefDefinition type) { if (type.IsPointer) { return(false); } switch (type.ManagedName) { case "Matrix3x3": case "Quaternion": case "Transform": case "Vector3": case "Vector4": return(true); default: return(false); } }
public TypeRefDefinition CopyTypeTemplated(TypeRefDefinition templateType, IDictionary <string, string> templateParams) { // Clang shows template parameters only as unexposed if (templateType.HasTemplateTypeParameter) { return(new TypeRefDefinition(templateParams[templateType.Name])); } if (templateType.Target != null) { // TODO: smarter replacement string specializedName = templateType.Target.FullyQualifiedName; foreach (var param in templateParams) { specializedName = specializedName.Replace(param.Key, param.Value); } if (!specializedName.Equals(templateType.Target.FullyQualifiedName)) { var specializedType = new TypeRefDefinition(specializedName) { Kind = templateType.Kind }; ResolveTypeRef(specializedType); return(specializedType); } } var t = new TypeRefDefinition { HasTemplateTypeParameter = templateType.HasTemplateTypeParameter, IsConst = templateType.IsConst, IsIncomplete = templateType.IsIncomplete, Name = templateType.Name, Referenced = templateType.Referenced != null?CopyTypeTemplated(templateType.Referenced, templateParams) : null, TemplateParams = templateType.TemplateParams?.Select(p => CopyTypeTemplated(p, templateParams)).ToList(), Target = templateType.Target, Kind = templateType.Kind }; return(t); }
public static string GetTypeSetterCSMarshal(TypeRefDefinition type) { if (!type.IsBasic) { switch (type.ManagedNameCS) { case "Matrix3x3": case "Quaternion": case "Transform": case "Vector3": case "Vector4": return("ref value"); } if (type.ManagedTypeRefName.Equals("IntPtr")) { return("value"); } return("value._native"); } return("value"); }
public TypeRefDefinition CopyTemplated(IDictionary <string, string> templateParams) { // Clang shows template parameters only as unexposed if (HasTemplateTypeParameter && Kind == TypeKind.Unexposed) { return(new TypeRefDefinition(templateParams[Name])); } var t = new TypeRefDefinition { HasTemplateTypeParameter = HasTemplateTypeParameter, IsConst = IsConst, IsIncomplete = IsIncomplete, Name = Name, Referenced = Referenced != null?Referenced.CopyTemplated(templateParams) : null, TemplateParams = TemplateParams?.Select(p => p.CopyTemplated(templateParams)).ToList(), Target = Target, Kind = Kind }; return(t); }
void ResolveTypeRef(TypeRefDefinition typeRef) { if (typeRef.IsBasic || typeRef.HasTemplateTypeParameter) { return; } if (typeRef.IsPointer || typeRef.IsReference || typeRef.IsConstantArray) { ResolveTypeRef(typeRef.Referenced); } else if (!classDefinitions.ContainsKey(typeRef.Name)) { // Search for unscoped enums bool resolvedEnum = false; foreach (var c in classDefinitions.Values.Where(c => c.Enum != null)) { if (typeRef.Name.Equals(c.FullName + "::" + c.Enum.Name)) { typeRef.Target = c; resolvedEnum = true; } } if (!resolvedEnum) { Console.WriteLine("Class " + typeRef.Name + " not found!"); } } else { typeRef.Target = classDefinitions[typeRef.Name]; } if (typeRef.SpecializedTemplateType != null) { ResolveTypeRef(typeRef.SpecializedTemplateType); } }
// If the type is defined in a conditionally compiled header, return the condition string. private string GetTypeConditional(TypeRefDefinition type) { var target = type.Target; if (target == null && type.Referenced != null) { target = type.Referenced.Target; } if (target == null) return null; string headerConditional; string targetHeaderName = DotNetParser.GetManaged(target.Header).Name; if (headerConditionals.TryGetValue(targetHeaderName, out headerConditional)) { return headerConditional; } return null; }
void AddForwardReference(List<ManagedClass> forwardRefs, TypeRefDefinition type, HeaderDefinition header) { if (type.IsBasic) return; switch (type.Kind) { case TypeKind.Pointer: case TypeKind.LValueReference: AddForwardReference(forwardRefs, type.Referenced, header); return; } var target = type.Target; if (target == null) return; if (target.IsExcluded || target.MarshalAsStruct || target.Header == header) return; var targetManaged = DotNetParser.GetManaged(target); if (!forwardRefs.Contains(targetManaged)) { forwardRefs.Add(targetManaged); } }
void WriteType(TypeRefDefinition type, WriteTo writeTo) { if (type.IsBasic) { Write(type.Name.Replace("::", "_"), writeTo & WriteTo.Header); Write(type.Name, writeTo & WriteTo.Source); } else if (type.HasTemplateTypeParameter) { } else { string typeName; if (type.Referenced != null) { if (type.Referenced.IsConst) // || type.IsConst { Write("const ", writeTo); } typeName = BulletParser.GetTypeName(type.Referenced) ?? string.Empty; } else { if (type.IsConst) { Write("const ", writeTo); } typeName = BulletParser.GetTypeName(type); } if (type.Target != null && type.Target.IsPureEnum) { Write(typeName + "::" + type.Target.Enum.Name, writeTo & WriteTo.Source); Write(typeName.Replace("::", "_"), writeTo & WriteTo.Header); } else { Write(typeName + '*', writeTo & WriteTo.Source); Write(typeName.Replace("::", "_") + '*', writeTo & WriteTo.Header); } } }
private string GetTypeName(TypeRefDefinition type) { if (type.Kind == TypeKind.Typedef) { if (type.Referenced.Kind == TypeKind.Pointer && type.Referenced.Referenced.Kind == TypeKind.FunctionProto) { return GetName(type); } if (type.Canonical.IsBasic) { return type.Name; } return GetTypeName(type.Referenced); } if (type.Kind == TypeKind.LValueReference) { return GetTypeName(type.Referenced); } if (!string.IsNullOrEmpty(type.Name) && type.Name.Equals("btAlignedObjectArray")) { if (type.TemplateParams != null) { return "Aligned" + GetName(type.TemplateParams[0]) + "Array^"; } } switch (type.Kind) { case TypeKind.Pointer: case TypeKind.LValueReference: case TypeKind.ConstantArray: if (type.Referenced.Kind == TypeKind.Void) { return "IntPtr"; } switch (GetName(type)) { case "char": return "String^"; case "float": return string.Format("array<{0}>^", type.Referenced.Name); } return GetName(type) + '^'; } return GetName(type); }
// Does the type require additional lines of code to marshal? public static bool TypeRequiresMarshal(TypeRefDefinition type) { switch (type.Kind) { case TypeKind.ConstantArray: case TypeKind.LValueReference: case TypeKind.Pointer: return TypeRequiresMarshal(type.Referenced); } return type.Target != null && type.Target.MarshalAsStruct; }
private static string GetTypeNameC(TypeRefDefinition type) { string name = ""; if (type.IsConst) { // Note: basic type can be const if (type.Referenced == null || (type.Referenced != null && !type.Referenced.ConstCanonical)) { name = "const "; } } if (type.IsBasic) return name + type.Name; if (type.Kind == TypeKind.Typedef) { if (type.Referenced.IsBasic) return type.Name; if (type.Referenced.Kind == TypeKind.Pointer && type.Referenced.Referenced.Kind == TypeKind.FunctionProto) { return type.Name; } return name + GetTypeNameC(type.Referenced); } if (type.Referenced != null) return name + GetTypeNameC(type.Referenced) + "*"; var target = type.Target; if (target != null && target is EnumDefinition) { if (target.Parent != null && target.Parent.IsPureEnum) { return target.Parent.FullName.Replace("::", "_"); } } // Template name to C form if (type.FullName.Contains("<")) { string template = type.FullName.Replace('<', '_').Replace(">", "").Replace(" *", "Ptr"); template = template.Replace(' ', '_'); return name + template.Replace("::", "_"); } return name + type.FullName.Replace("::", "_"); }
// Return condition unless type is already used under the same condition. string GetTypeConditional(TypeRefDefinition type, HeaderDefinition header) { string typeConditional = GetTypeConditional(type); if (typeConditional != null && headerConditionals.ContainsKey(header.ManagedName)) { if (headerConditionals[header.ManagedName].Equals(typeConditional)) { return null; } } return typeConditional; }
public TypeRefDefinition CopyTypeTemplated(TypeRefDefinition templateType, IDictionary<string, string> templateParams) { // Clang shows template parameters only as unexposed if (templateType.HasTemplateTypeParameter) { return new TypeRefDefinition(templateParams[templateType.Name]); } if (templateType.Target != null) { // TODO: smarter replacement string specializedName = templateType.Target.FullyQualifiedName; foreach (var param in templateParams) { specializedName = specializedName.Replace(param.Key, param.Value); } if (!specializedName.Equals(templateType.Target.FullyQualifiedName)) { var specializedType = new TypeRefDefinition(specializedName) { Kind = templateType.Kind }; ResolveTypeRef(specializedType); return specializedType; } } var t = new TypeRefDefinition { HasTemplateTypeParameter = templateType.HasTemplateTypeParameter, IsConst = templateType.IsConst, IsIncomplete = templateType.IsIncomplete, Name = templateType.Name, Referenced = templateType.Referenced != null ? CopyTypeTemplated(templateType.Referenced, templateParams) : null, TemplateParams = templateType.TemplateParams?.Select(p => CopyTypeTemplated(p, templateParams)).ToList(), Target = templateType.Target, Kind = templateType.Kind }; return t; }
public TypeRefDefinition(ClangSharp.Type type, Cursor cursor = null) { Kind = (TypeKind)type.TypeKind; if (!type.Declaration.IsInvalid && !type.Declaration.IsDefinition && type.Declaration.SpecializedCursorTemplate.IsInvalid) { // Forward reference IsIncomplete = true; } IsConst = type.IsConstQualifiedType; if (type.Pointee.TypeKind != ClangSharp.Type.Kind.Invalid) { Cursor pointeeCursor = cursor?.Children.FirstOrDefault(c => c.Type.Equals(type.Pointee)); if (pointeeCursor == null) { pointeeCursor = cursor?.Children.FirstOrDefault(c => c.Kind == CursorKind.TypeRef)?.Referenced; } Referenced = new TypeRefDefinition(type.Pointee, pointeeCursor); } else if (Kind != TypeKind.Typedef) { if (cursor != null && (Kind == TypeKind.Record || Kind == TypeKind.Unexposed)) { if (cursor.Kind == CursorKind.TypeRef) { if (cursor.Referenced.Kind == CursorKind.TemplateTypeParameter) { HasTemplateTypeParameter = true; } } else if (cursor.Kind == CursorKind.CxxMethod) { var children = cursor.Children.TakeWhile(c => c.Kind != CursorKind.ParmDecl); var typeRef = children.FirstOrDefault(); if (typeRef != null && typeRef.Kind == CursorKind.TypeRef) { if (typeRef.Referenced.Kind == CursorKind.TemplateTypeParameter) { HasTemplateTypeParameter = true; } } } else if (cursor.Kind == CursorKind.ParmDecl) { var typeRef = cursor.Children.FirstOrDefault(); if (typeRef != null && typeRef.Kind == CursorKind.TypeRef) { if (typeRef.Referenced.Kind == CursorKind.TemplateTypeParameter) { HasTemplateTypeParameter = true; } } } } // Capture template parameters var firstChild = cursor?.Children.FirstOrDefault(); if (firstChild != null && firstChild.Kind == CursorKind.TemplateRef) { if (cursor.Children.Count == 1) { string displayName = GetFullyQualifiedName(type, cursor); int typeStart = displayName.IndexOf('<') + 1; int typeEnd = displayName.LastIndexOf('>'); displayName = displayName.Substring(typeStart, typeEnd - typeStart); TemplateParams = new List<TypeRefDefinition> { new TypeRefDefinition(displayName) }; } else { TemplateParams = cursor.Children.Skip(1) .Select(c => new TypeRefDefinition(c.Type, c)).ToList(); } } } switch (Kind) { case TypeKind.Void: case TypeKind.Bool: case TypeKind.Char_S: case TypeKind.Double: case TypeKind.Float: case TypeKind.Int: case TypeKind.UChar: case TypeKind.UInt: Name = type.Spelling; break; case TypeKind.Long: Name = "long"; break; case TypeKind.LongLong: Name = "long long"; break; case TypeKind.Short: Name = "short"; break; case TypeKind.ULong: Name = "unsigned long"; break; case TypeKind.ULongLong: Name = "unsigned long long"; break; case TypeKind.UShort: Name = "unsigned short"; break; case TypeKind.Typedef: Name = GetFullyQualifiedName(type); Referenced = new TypeRefDefinition(type.Canonical, cursor?.Referenced); break; case TypeKind.FunctionProto: case TypeKind.LValueReference: case TypeKind.Pointer: break; case TypeKind.ConstantArray: Referenced = new TypeRefDefinition(type.ArrayElementType, cursor); break; case TypeKind.Enum: Name = type.Canonical.Declaration.Spelling; break; case TypeKind.Record: Name = GetFullyQualifiedName(type, cursor); break; case TypeKind.Unexposed: if (type.Canonical.TypeKind != ClangSharp.Type.Kind.Unexposed) { Kind = (TypeKind)type.Canonical.TypeKind; Name = GetFullyQualifiedName(type.Canonical, cursor); } else { Name = GetFullyQualifiedName(type, cursor); } break; case TypeKind.DependentSizedArray: break; default: throw new NotImplementedException(); } }
void AddForwardReference(List<ClassDefinition> forwardRefs, TypeRefDefinition type, HeaderDefinition header) { if (type.IsBasic) { return; } if (type.IsPointer || type.IsReference) { AddForwardReference(forwardRefs, type.Referenced, header); return; } if (type.Target == null) { return; } if (type.Target.IsExcluded || forwardRefs.Contains(type.Target) || PrecompiledHeaderReferences.Contains(type.Target.ManagedName)) { return; } // Forward ref to class in another header if (type.Target.Header != header) { forwardRefs.Add(type.Target); } }
public static string GetTypeDllImport(TypeRefDefinition type) { switch (type.ManagedNameCS) { case "Matrix3x3": case "Quaternion": case "Transform": case "Vector3": case "Vector4": { if (type.Referenced != null && !(type.IsConst || type.Referenced.IsConst)) { return "[Out] out " + GetTypeNameCS(type); } return "[In] ref " + GetTypeNameCS(type); } } if (type.Referenced != null && !type.IsBasic) { if ("btScalar".Equals(type.Referenced.Name)) { if (type.IsPointer) { return type.ManagedNameCS + "[]"; } else { // reference if (!(type.IsConst || type.Referenced.IsConst)) { return "[Out] out " + type.ManagedNameCS; } } } return "IntPtr"; } return type.ManagedNameCS; }
private string GetTypeNameCS(TypeRefDefinition type) { if (type.Kind == TypeKind.Typedef) { if (type.Referenced.Kind == TypeKind.Pointer && type.Referenced.Referenced.Kind == TypeKind.FunctionProto) { return GetName(type); } return GetTypeNameCS(type.Referenced); } if (type.Kind == TypeKind.LValueReference) { return GetTypeNameCS(type.Referenced); } if (type.IsBasic) { switch (type.Kind) { case TypeKind.UShort: return "ushort"; case TypeKind.UInt: return "uint"; case TypeKind.ULong: return "ulong"; } return GetName(type); } if (type.Kind == TypeKind.Pointer && type.Referenced.Kind == TypeKind.Void) { return "IntPtr"; } if (type.Kind == TypeKind.ConstantArray) { switch (type.Referenced.Name) { case "bool": return "BoolArray"; case "int": return "IntArray"; case "unsigned int": return "UIntArray"; case "unsigned short": return "UShortArray"; case "btScalar": return "FloatArray"; case "btDbvt": return "DbvtArray"; case "btSoftBody::Body": return "BodyArray"; } if (type.Referenced.Referenced != null) { switch (type.Referenced.Referenced.Name) { case "btDbvtNode": return "DbvtNodePtrArray"; case "btDbvtProxy": return "DbvtProxyPtrArray"; case "btSoftBody::Node": return "NodePtrArray"; } } return GetTypeNameCS(type.Referenced) + "[]"; } return GetName(type); }
// Does the type require additional lines of code to marshal? public static bool TypeRequiresMarshal(TypeRefDefinition type) { switch (type.ManagedName) { case "Matrix3x3": case "Quaternion": case "Transform": case "Vector3": case "Vector4": return true; default: return false; } }
public TypeRefDefinition Copy() { var t = new TypeRefDefinition { HasTemplateTypeParameter = HasTemplateTypeParameter, IsBasic = IsBasic, IsConst = IsConst, IsConstantArray = IsConstantArray, IsIncomplete = IsIncomplete, IsPointer = IsPointer, IsReference = IsReference, Name = Name, Referenced = Referenced, SpecializedTemplateType = SpecializedTemplateType, Target = Target }; return t; }
void WriteType(TypeRefDefinition type, WriteTo writeTo) { string typeName = BulletParser.GetTypeName(type) ?? string.Empty; Write(typeName.Replace("::", "_"), writeTo & (WriteTo.Source | WriteTo.Header)); }
private void ResolveInclude(TypeRefDefinition type, HeaderDefinition parentHeader) { switch (type.Kind) { case TypeKind.Pointer: case TypeKind.LValueReference: case TypeKind.ConstantArray: ResolveInclude(type.Referenced, parentHeader); return; } if (type.TemplateParams != null) { type.TemplateParams.ForEach(p => ResolveInclude(p, parentHeader)); } else if (type.IsIncomplete && type.Target != null) { if (type.Target.MarshalAsStruct) return; parentHeader.Includes.Add(type.Target.Header); } }
// If the type is defined in a conditionally compiled header, return the condition string. string GetTypeConditional(TypeRefDefinition type) { var target = type.Target; if (target == null && type.Referenced != null) { target = type.Referenced.Target; } if (target != null && headerConditionals.ContainsKey(target.Header.ManagedName)) { return headerConditionals[target.Header.ManagedName]; } return null; }
public static string GetReturnValueMarshalStart(TypeRefDefinition type) { switch (type.ManagedName) { case "Quaternion": case "Matrix3x3": case "Transform": case "Vector3": case "Vector4": if (type.IsPointer) { return type.ManagedName.ToUpper() + "_OUT("; } if (type.IsReference) { return type.ManagedName.ToUpper() + "_OUT(&"; } return type.ManagedName.ToUpper() + "_OUT_VAL("; default: return null; } }
public TypeRefDefinition(ClangSharp.Type type) { if (!type.Declaration.IsInvalid && !type.Declaration.IsDefinition && type.Declaration.SpecializedCursorTemplate.IsInvalid) { // Forward reference IsIncomplete = true; } IsConst = type.IsConstQualifiedType; switch (type.TypeKind) { case ClangSharp.Type.Kind.Void: case ClangSharp.Type.Kind.Bool: case ClangSharp.Type.Kind.CharS: case ClangSharp.Type.Kind.Double: case ClangSharp.Type.Kind.Float: case ClangSharp.Type.Kind.Int: case ClangSharp.Type.Kind.UChar: case ClangSharp.Type.Kind.UInt: Name = type.Spelling; IsBasic = true; break; case ClangSharp.Type.Kind.Long: Name = "long"; IsBasic = true; break; case ClangSharp.Type.Kind.LongLong: Name = "long long"; IsBasic = true; break; case ClangSharp.Type.Kind.Short: Name = "short"; IsBasic = true; break; case ClangSharp.Type.Kind.ULong: Name = "unsigned long"; IsBasic = true; break; case ClangSharp.Type.Kind.UShort: Name = "unsigned short"; IsBasic = true; break; case ClangSharp.Type.Kind.Typedef: Name = GetFullyQualifiedName(type); Referenced = new TypeRefDefinition(type.Canonical); IsBasic = Referenced.IsBasic; break; case ClangSharp.Type.Kind.Pointer: Referenced = new TypeRefDefinition(type.Pointee); IsPointer = true; break; case ClangSharp.Type.Kind.LValueReference: Referenced = new TypeRefDefinition(type.Pointee); IsReference = true; break; case ClangSharp.Type.Kind.ConstantArray: Referenced = new TypeRefDefinition(type.ArrayElementType); IsConstantArray = true; break; case ClangSharp.Type.Kind.FunctionProto: // ?? break; case ClangSharp.Type.Kind.Enum: Name = type.Canonical.Declaration.Spelling; IsBasic = true; break; case ClangSharp.Type.Kind.Record: case ClangSharp.Type.Kind.Unexposed: Name = GetFullyQualifiedName(type); break; case ClangSharp.Type.Kind.DependentSizedArray: break; default: throw new NotImplementedException(); } }
private static string GetTypeSetterCSMarshal(TypeRefDefinition type) { type = type.Canonical; if ((type.Target != null && type.Target.MarshalAsStruct) || (type.Kind == TypeKind.LValueReference && type.Referenced.Target != null && type.Referenced.Target.MarshalAsStruct)) { return "ref value"; } if (!type.IsBasic) { if (type.Kind == TypeKind.Pointer && type.Referenced.Kind == TypeKind.Void) { return "value"; } return "value._native"; } return "value"; }
public TypeRefDefinition(string name) { switch (name) { case "bool": Kind = TypeKind.Bool; break; case "char": Kind = TypeKind.Char_U; break; case "double": Kind = TypeKind.Double; break; case "float": Kind = TypeKind.Float; break; case "int": Kind = TypeKind.Int; break; case "unsigned char": Kind = TypeKind.UChar; break; case "unsigned int": Kind = TypeKind.UInt; break; case "void": Kind = TypeKind.Void; break; case "long": case "long int": Kind = TypeKind.Long; break; case "long long": case "long long int": Kind = TypeKind.LongLong; break; case "short": case "short int": Kind = TypeKind.Short; break; case "unsigned long": case "unsigned long int": Kind = TypeKind.ULong; break; case "unsigned long long": case "unsigned long long int": Kind = TypeKind.ULongLong; break; case "unsigned short": case "unsigned short int": Kind = TypeKind.UShort; break; } if (IsBasic) { Name = GetBasicName(name); } else if (name.EndsWith(" *")) { Referenced = new TypeRefDefinition(name.Substring(0, name.Length - 2)); Kind = TypeKind.Pointer; } else { Name = name; } }
public TypeRefDefinition Copy() { var t = new TypeRefDefinition { HasTemplateTypeParameter = HasTemplateTypeParameter, IsConst = IsConst, IsIncomplete = IsIncomplete, Name = Name, Referenced = Referenced != null ? Referenced.Copy() : null, TemplateParams = TemplateParams?.Select(p => p.Copy()).ToList(), Target = Target, Kind = Kind }; return t; }
void WriteMethod(MethodDefinition method, int level, ref int overloadIndex, int numOptionalParams = 0, MethodDefinition returnParamMethod = null) { // Can't return whole structures, so append an output parameter // referencing the struct that will hold the return value. // convert "v method(param)" to "void method(param, &v)" if (!method.IsConstructor && !method.ReturnType.IsBasic && !method.ReturnType.IsPointer && BulletParser.MarshalStructByValue(method.ReturnType)) { var method2 = method.Copy(); var paras = method2.Parameters; Array.Resize<ParameterDefinition>(ref paras, paras.Length + 1); string paramName; if (method.Property != null && method.Property.Setter != null) { // Borrow out parameter name from setter paramName = method.Property.Setter.Parameters[0].Name; } else { paramName = "value"; } var valueType = new TypeRefDefinition() { IsBasic = false, IsPointer = true, Referenced = method2.ReturnType }; paras[paras.Length - 1] = new ParameterDefinition(paramName, valueType); paras[paras.Length - 1].ManagedName = paramName; method2.Parameters = paras; method2.ReturnType = new TypeRefDefinition(); WriteMethod(method2, level, ref overloadIndex, numOptionalParams, method); return; } EnsureWhiteSpace(WriteTo.Source | WriteTo.CS); // Skip methods wrapped by C# properties WriteTo propertyTo = WriteTo.Header | WriteTo.Source | ((method.Property == null) ? WriteTo.CS : 0); int numOptionalParamsTotal = method.NumOptionalParameters; int numParameters = method.Parameters.Length - numOptionalParamsTotal + numOptionalParams; WriteMethodDeclaration(method, numParameters, level, overloadIndex, returnParamMethod); if (method.Name.Equals("delete")) { WriteLine('{', WriteTo.Source); WriteTabs(1, WriteTo.Source); WriteLine("delete obj;", WriteTo.Source); WriteLine('}', WriteTo.Source); hasSourceWhiteSpace = false; hasCSWhiteSpace = false; return; } // Constructor base call if (method.IsConstructor && method.Parent.BaseClass != null) { WriteTabs(level + 2, WriteTo.CS & propertyTo); Write(": base(", WriteTo.CS & propertyTo); } else { WriteTabs(level + 1, WriteTo.CS & propertyTo); WriteLine('{', WriteTo.CS & propertyTo); WriteTabs(level + 2, WriteTo.CS & propertyTo); } // Method body WriteLine('{', WriteTo.Source); WriteMethodDefinition(method, numParameters, overloadIndex, level, returnParamMethod); WriteTabs(level + 1, WriteTo.CS & propertyTo); WriteLine('}', WriteTo.Source | WriteTo.CS & propertyTo); hasSourceWhiteSpace = false; if (method.Property == null) { hasCSWhiteSpace = false; } // If there are optional parameters, then output all possible combinations of calls overloadIndex++; if (numOptionalParams < numOptionalParamsTotal) { WriteMethod(method, level, ref overloadIndex, numOptionalParams + 1, returnParamMethod); } }
private void CreateFieldSetter(FieldDefinition field, ClassDefinition @class, string setterName) { var type = field.Type; var typeCanonical = type.Canonical; // Can't assign value to reference or constant array switch (typeCanonical.Kind) { case TypeKind.LValueReference: case TypeKind.ConstantArray: return; case TypeKind.Record: if (typeCanonical.Target == null) return; if (!typeCanonical.Target.MarshalAsStruct) return; type = new TypeRefDefinition { IsConst = true, Kind = TypeKind.Pointer, Referenced = type.Copy() }; break; default: type = type.Copy(); break; } var setter = new MethodDefinition(setterName, @class, 1) { Field = field, ReturnType = new TypeRefDefinition("void") }; setter.Parameters[0] = new ParameterDefinition("value", type) { MarshalDirection = MarshalDirection.In }; field.Setter = setter; }