private Dictionary <string, string> GenerateVTable(Definitions.ClassDefinition classDefinition) { Dictionary <string, string> VTable; if (classDefinition.ClassType.BaseClassType == null) { VTable = new Dictionary <string, string>(); for (int x = 0; x < classDefinition.Methods.Count; x++) { string MethodName = classDefinition.Methods.ItemAt(x).Name; VTable.Add(MethodName, classDefinition.Name); } } else { VTable = GenerateVTable(Analysis.Environment.Classes.Lookup(classDefinition.ClassType.BaseClassType.Name)); for (int x = 0; x < classDefinition.Methods.Count; x++) { string MethodName = classDefinition.Methods.ItemAt(x).Name; if (VTable.ContainsKey(MethodName)) { VTable[MethodName] = classDefinition.Name; } else { VTable.Add(MethodName, classDefinition.Name); } } } return(VTable); }
private int SizeOf(Definitions.ClassDefinition classDefinition) { int Size = classDefinition.Fields.Count * 4; if (classDefinition.ClassType.BaseClassType != null) { Size += SizeOf(Analysis.Environment.Classes.Lookup(classDefinition.ClassType.BaseClassType.Name)); } return(Size); }
//-------------------------------------------------------------------------------------------------- void GenerateClassSource(StringWriter w, Definitions.ClassDefinition cd) { w.WriteLine(); w.WriteLine("//---------------------------------------------------------------------"); w.WriteLine($"// Class {cd.Name}"); w.WriteLine("//---------------------------------------------------------------------"); w.WriteLine(); // write methods foreach (var fd in cd.Functions) { if (fd.IsDestructor || !fd.IsPublic) { continue; } for (int i = fd.Parameters.Count; i >= (fd.Parameters.Count - fd.DefaultParameterCount); i--) { if (cd.Functions.Any(ffd => (ffd != fd) && ffd.IsEqual(fd, i))) { break; } GenerateFunctionSource(w, fd, i); } } w.WriteLine(); // Downcast method if (cd.IsTransient) { w.WriteLine($"{cd.Fqn}^ {cd.Fqn}::CreateDowncasted({cd.Native}* instance)"); w.WriteLine("{"); if (cd.DerivedClasses.Any()) { w.WriteLine("\tif( instance == nullptr )"); w.WriteLine("\t\treturn nullptr;"); w.WriteLine(""); foreach (var derivedClass in cd.DerivedClasses) { w.WriteLine($"\tif (instance->IsKind(STANDARD_TYPE({derivedClass.Native})))"); w.WriteLine($"\t\treturn {derivedClass.Fqn}::CreateDowncasted(({derivedClass.Native}*)instance);"); } w.WriteLine(""); } w.WriteLine($"\treturn gcnew {cd.Fqn}( instance );"); w.WriteLine("}"); w.WriteLine(); } w.WriteLine(); }
//-------------------------------------------------------------------------------------------------- void _AddFunction(Definitions.ClassDefinition klass, CastXml.Method method, int funcType) { var fName = funcType == 0 ? method.name : klass.Name; var logName = klass.Name + "::" + fName; if (Configuration.Ignore.Contains(klass.Name + "::" + fName) || Configuration.Ignore.Contains("*::" + fName)) { Logger.WriteLine(true, "Function " + logName + " ignored by definition."); return; } if (fName.StartsWith("_CSFDB_")) { Logger.WriteLine(true, "Function " + logName + " ignored because it begins with _CSFDB_"); return; } // Create function var f = new Definitions.FunctionDefintion() { Class = klass, Name = fName, Type = (funcType == 0) ? _GetTypeDefinition(method.returns) : _VoidTypeDefinition, IsStatic = method.IsStatic, IsPublic = method.IsPublic, IsConstructor = funcType == 1, IsDestructor = funcType == 2, IsOperator = false, IsTemplate = fName.Contains('<'), IsAbstract = method.IsPureVirtual, }; if (f.Type == null) { Logger.WriteLine(true, string.Format("\tFunction " + logName + " ignored because of an unknown return type (FunctionType?).")); return; } Logger.WriteLine(true, string.Format("\tRelevant function: [{0}] {1} type='{2}'", method.id, fName, f.Type.Name)); // Get parameters int unnamedCount = 1; if (method.Argument != null) { foreach (var p in method.Argument) { var fp = new Definitions.ParameterDefinition { Type = _GetTypeDefinition(p.type) }; if (fp.Type == null) { Logger.WriteLine(true, string.Format("\tFunction " + logName + " ignored because of an unknown parameter type (FunctionType?).")); return; } if (string.IsNullOrEmpty(p.name)) { fp.Name = $"parameter{unnamedCount}"; unnamedCount++; } else { fp.Name = p.name; } if (Configuration.NameReplacements.ContainsKey(fp.Name)) { fp.Name = Configuration.NameReplacements[fp.Name]; } if (!string.IsNullOrEmpty(p.@default)) { fp.Default = [email protected](TrimChars); // Make sure any type is interpreted as native, not wrapped if (fp.Default.StartsWith("opencascade::handle<")) { fp.Default = fp.Default.Insert(20, "::"); } else if (fp.Default.EndsWith("()")) // Constructor { fp.Default = "::" + fp.Default; } fp.HasDefault = true; } Logger.WriteLine(true, $"\t\tRelevant parameter: {fp.Name} type='{fp.Type.Name}' default='{fp.Default}'"); f.Parameters.Add(fp); } if (f.Parameters.All(pd => pd.Type.IsVoid && !pd.Type.IsPointer)) { // Only one void parameter, thats equivalent to no parameter Logger.WriteLine(true, "\t\tFunction " + logName + " cleared all parameters because it has only one of type void."); f.Parameters.Clear(); } } if (!klass.Functions.Any(other => f.IsEqual(other))) { klass.Functions.Add(f); } }
//-------------------------------------------------------------------------------------------------- Definitions.ClassDefinition _AddClass(CastXml.Record record, string package, bool isStruct, string overrideName = null) { string className = string.IsNullOrEmpty(overrideName) ? record.name : overrideName; if (string.IsNullOrEmpty(className) || className.StartsWith("Handle_")) { return(null); } if (Configuration.Ignore.Contains(className)) { Logger.WriteLine(true, "Class " + className + " ignored by definition."); return(null); } if (Configuration.KnownTypes.Any(def => def.NativeFqn == className)) { Logger.WriteLine(true, "Class " + className + " already in known types list."); return(null); } if (Configuration.ClassOptInList.ContainsKey(package)) { // OptIn-Package if (!Configuration.ClassOptInList[package].Contains(className)) { Logger.WriteLine(true, "Class " + className + " ignored beacause of opt-in package."); return(null); } } var c = new Definitions.ClassDefinition() { Name = className, Package = package, IsStruct = isStruct, IsAbstract = record.IsAbstract }; Definitions.ClassItems.Add(c); // Search for base class var baseClassToCopyIds = new List <string>(); if (record.Base != null) { foreach (var baseElement in record.Base) { var baseTypeId = baseElement.type; var baseClassElement = _Db.Classes.FirstOrDefault(e => e.id == baseTypeId); if (baseClassElement != null) { var baseClassName = baseClassElement.name; // Take base class name only if it is not template. if (baseClassName.Contains("<")) { baseClassToCopyIds.Add(baseTypeId); continue; } c.BaseClassName = baseClassName; break; } } } var classId = record.id; Logger.WriteLine(true, $"Relevant class: [{classId}] {className} : {c.BaseClassName}"); // Search for constructors in class var constructors = from item in _Db.Constructors where item.context == classId select item; foreach (var f in constructors) { _AddFunction(c, f, 1); } // Search for destructors in class var destructors = from item in _Db.Destructors where item.context == classId select item; foreach (var f in destructors) { _AddFunction(c, f, 2); } // Search for functions in class var functions = from item in _Db.Methods where item.context == classId select item; foreach (var f in functions) { _AddFunction(c, f, 0); } // Search for functions in base class to copy // e.g. if the base class was templated foreach (var id in baseClassToCopyIds) { var baseFuncs = from item in _Db.Methods where item.context == id select item; foreach (var f in baseFuncs) { _AddFunction(c, f, 0); } } // Search for inner enums var enums = from item in _Db.Enumerations where item.context == classId select item; foreach (var e in enums) { _AddEnum(e, e.id, package, c); } _AddInclude(record.file); return(c); }
//-------------------------------------------------------------------------------------------------- bool _AddEnum(CastXml.ItemsEnumeration enumeration, string enumId, string package, Definitions.ClassDefinition c = null) { var name = enumeration.name; if (string.IsNullOrEmpty(name)) { return(true); } if (Configuration.KnownTypes.Any(def => def.NativeFqn == name)) { Logger.WriteLine(true, "Enum " + name + " already in known types list."); return(true); } if (Configuration.ClassOptInList.ContainsKey(package)) { // OptIn-Package if (!Configuration.ClassOptInList[package].Contains(name)) { Logger.WriteLine(true, "Enum " + name + " ignored beacause of opt-in package."); return(true); } } Logger.WriteLine(true, $"Relevant enum: [{enumeration.id}] [{enumId}] {name}"); var e = new Definitions.EnumDefinition() { Name = name, Package = package, OuterClass = c }; if (c == null) { Definitions.EnumItems.Add(e); } else { if (e.Name.Contains("::")) { e.Name = e.Name.Remove(0, e.Name.LastIndexOf(":", StringComparison.Ordinal)); } c.InnerEnums.Add(e); } foreach (var enumValue in enumeration.EnumValue) { e.Enumerators.Add(enumValue.name, enumValue.init.ToString()); } _AddInclude(enumeration.file); return(true); }
//-------------------------------------------------------------------------------------------------- void GenerateClassHeaderInstance(StringWriter w, Definitions.ClassDefinition cd) { if (cd.IsStatic) { return; } // write default constructor, if the native class doesn't have one if (!cd.HasDefaultConstructor) { // Only create a default constructor, if the class does not have any constructor // AND the class isn't abstract AND does not define the constructor inaccessible // AND any constructor was found bit ignored. if (!(cd.HasConstructor || cd.IsAbstract || cd.HasUnaccessibleConstructor || cd.HasAbstractFunctions || Configuration.Ignore.Contains(cd.Name + "::" + cd.Name))) { // Create public default constructor w.WriteLine("public:"); w.WriteLine("\t" + cd.Name + "()"); w.WriteLine($"\t\t: {cd.SuperClassFqn}(InitMode::Uninitialized)"); w.WriteLine("\t{"); w.WriteLine("\t\t_NativeInstance = new " + cd.Native + "();"); w.WriteLine("\t}"); w.WriteLine(); } } if (cd.IsBase || Configuration.Unseal.Contains(cd.Name)) { // Default constructor (uninitialized) w.WriteLine("protected:"); w.WriteLine($"\t{cd.Name}(InitMode init)"); w.WriteLine($"\t\t: {cd.SuperClassFqn}( init )"); w.WriteLine("\t{}"); w.WriteLine(); } w.WriteLine("public:"); // Constructor for instance pointer w.WriteLine("\t" + cd.Name + "(" + cd.Native + "* nativeInstance)"); if (cd.BaseClass == null && !cd.IsTransient) { w.WriteLine($"\t\t: {cd.SuperClassFqn}( nativeInstance, true )"); } else { w.WriteLine($"\t\t: {cd.SuperClassFqn}( nativeInstance )"); } w.WriteLine("\t{}"); w.WriteLine(); // Constructor for instance reference w.WriteLine($"\t{cd.Name}({cd.Native}& nativeInstance)"); if (cd.BaseClass == null && !cd.IsTransient) { w.WriteLine($"\t\t: {cd.SuperClassFqn}( &nativeInstance, false )"); } else { w.WriteLine($"\t\t: {cd.SuperClassFqn}( nativeInstance )"); } w.WriteLine("\t{}"); w.WriteLine(); // Create property for instance reference w.WriteLine($"\tproperty {cd.Native}* NativeInstance"); w.WriteLine("\t{"); w.WriteLine("\t\t" + cd.Native + "* get()"); w.WriteLine("\t\t{"); w.WriteLine($"\t\t\treturn static_cast<{cd.Native}*>(_NativeInstance);"); w.WriteLine("\t\t}"); w.WriteLine("\t}"); w.WriteLine(); // Create Downcast function if (cd.IsTransient) { w.WriteLine("\tstatic " + cd.Fqn + "^ CreateDowncasted(" + cd.Native + "* instance);"); w.WriteLine(); } }
void GenerateClassHeader(StringWriter w, Definitions.ClassDefinition cd, bool inner = false) { if (!inner) { w.WriteLine("//---------------------------------------------------------------------"); w.WriteLine("// Class " + cd.Name); w.WriteLine("//---------------------------------------------------------------------"); } if (!inner) { w.Write("public "); } w.Write("ref class {0}", cd.Name); if (!(cd.IsBase || cd.IsAbstract || Configuration.Unseal.Contains(cd.Name))) { w.Write(" sealed"); } // Has baseclass if (!cd.IsStatic) { w.Write($" : public {cd.SuperClassFqn}"); } w.WriteLine(); w.WriteLine("{"); // Write macro w.WriteLine(); w.WriteLine("#ifdef Include_" + (inner ? (cd.OuterClass.Name + "_") : "") + cd.Name + "_h"); w.WriteLine("public:"); w.WriteLine("\tInclude_" + (inner ? (cd.OuterClass.Name + "_") : "") + cd.Name + "_h"); w.WriteLine("#endif"); w.WriteLine(); // Write instance handling GenerateClassHeaderInstance(w, cd); w.WriteLine("public:"); // write inner enums foreach (var ed in cd.InnerEnums) { GenerateEnumHeader(w, ed, true); } // write inner classes foreach (var icd in cd.InnerClasses) { GenerateClassHeader(w, icd, true); } // write methods foreach (var fd in cd.Functions) { if (fd.IsDestructor || !fd.IsPublic) { continue; } for (int i = fd.Parameters.Count; i >= (fd.Parameters.Count - fd.DefaultParameterCount); i--) { if (cd.Functions.Any(ffd => (ffd != fd) && ffd.IsEqual(fd, i))) { break; } w.Write("\t"); GenerateFunctionDeclaration(w, fd, i); } } w.WriteLine("}}; // class {0}", cd.Name); w.WriteLine(); }
//-------------------------------------------------------------------------------------------------- bool GenerateTypeDecl(StringWriter w, Definitions.TypeDefinition type, Definitions.ClassDefinition klass, bool isReturnType) { if (string.IsNullOrWhiteSpace(type.Name)) { return(false); } if (type.IsKnownType) { // Known type if (type.KnownTypeDef.Type == Definitions.KnownTypes.Void) { if (type.IsPointer) { w.Write("System::IntPtr"); } else { w.Write("void"); } } else if (type.KnownTypeDef.Type == Definitions.KnownTypes.VoidPtr) { w.Write("System::IntPtr"); } else if (type.KnownTypeDef.IsValueType) { w.Write(type.KnownTypeDef.Fqn); if (!isReturnType && (type.IsPointer || type.IsReference) && !type.IsConst) { w.Write("%"); } } else { w.Write(type.KnownTypeDef.Fqn + "^"); } } else if (klass.HasInnerEnum(type.Name)) { // Known enum w.Write(klass.InnerEnum(type.Name).Fqn); if (!isReturnType && type.IsReference) { w.Write("%"); } } else if (type.IsEnum(klass)) { // Known enum w.Write(type.Fqn(klass)); if (!isReturnType && type.IsReference) { w.Write("%"); } } else if (Definitions.ClassItems.Any(cd => cd.Name.Equals(type.Name))) { // Known class w.Write(Definitions.ClassItems.First(cd => cd.Name.Equals(type.Name)).Fqn + "^"); } else if (klass.InnerClasses.Any(cd => cd.Name.Equals(type.Name))) { // Known inner class w.Write(klass.InnerClasses.First(cd => cd.Name.Equals(type.Name)).Fqn + "^"); } else { // Unknown class, write as native if (!Configuration.UnknownTypes.Contains(type.Name)) { type.IsUnknown = true; Configuration.UnknownTypes.Add(type.Name); Logger.WriteLine(true, "Unknown type: " + type.Name); } return(false); } w.Write(" "); return(true); }