/* * Defines an Enum. */ private CodeTypeDeclaration DefineEnum(string cppName) { int colon = cppName.LastIndexOf("::", StringComparison.Ordinal); string prefix = string.Empty; if (colon != -1) { prefix = cppName.Substring(0, colon); } string name = cppName; if (colon != -1) { name = cppName.Substring(colon + 2); } // HACK: in qprinter.h there is a typedef PageSize PaperSize; but PageSize is obsolete; using PaperSize; remove when the typedef maps are added to SMOKE if (cppName == "QPrinter::PageSize") { name = "PaperSize"; } CodeTypeDeclaration typeDecl = new CodeTypeDeclaration(name); typeDecl.IsEnum = true; if (!data.ReferencedTypeMap.ContainsKey(name) || data.ReferencedTypeMap[name].FullName != data.DefaultNamespace.Name + "." + cppName.Replace("::", "+")) { data.GetTypeCollection(prefix).Add(typeDecl); typeDecl.UserData.Add("parent", prefix); data.EnumTypeMap[cppName] = typeDecl; } return(typeDecl); }
/* * Create a .NET class from a smoke class. * A class Namespace::Foo is mapped to Namespace.Foo. Classes that are not in any namespace go into the default namespace. * For namespaces that contain functions, a Namespace.Global class is created which holds the functions as methods. */ private void DefineClass(short classId) { Smoke.Class *smokeClass = data.Smoke->classes + classId; string smokeName = ByteArrayManager.GetString(smokeClass->className); string mapName = smokeName; string name; string prefix = string.Empty; if (smokeClass->size == 0 && !translator.NamespacesAsClasses.Contains(smokeName)) { if (smokeName == "QGlobalSpace") { // global space name = data.GlobalSpaceClassName; mapName = name; } else { // namespace prefix = smokeName; name = "Global"; mapName = prefix + "::Global"; } } else { int colon = smokeName.LastIndexOf("::", StringComparison.Ordinal); prefix = (colon != -1) ? smokeName.Substring(0, colon) : string.Empty; name = (colon != -1) ? smokeName.Substring(colon + 2) : smokeName; } // define the .NET class CodeTypeDeclaration type; bool alreadyDefined; if (!(alreadyDefined = data.CSharpTypeMap.TryGetValue(mapName, out type))) { type = new CodeTypeDeclaration(name); CodeAttributeDeclaration attr = new CodeAttributeDeclaration("SmokeClass", new CodeAttributeArgument( new CodePrimitiveExpression(smokeName))); type.CustomAttributes.Add(attr); type.IsPartial = true; } else { int toBeRemoved = -1; for (int i = 0; i < type.CustomAttributes.Count; i++) { CodeAttributeDeclaration attr = type.CustomAttributes[i]; if (attr.Name == "SmokeClass" && attr.Arguments.Count == 1 && ((string)((CodePrimitiveExpression)attr.Arguments[0].Value).Value) == "QGlobalSpace") { toBeRemoved = i; break; } } if (toBeRemoved > -1) { type.CustomAttributes.RemoveAt(toBeRemoved); CodeAttributeDeclaration attr = new CodeAttributeDeclaration("SmokeClass", new CodeAttributeArgument( new CodePrimitiveExpression(smokeName))); type.CustomAttributes.Add(attr); } } if (smokeClass->parents != 0) { short *parent = data.Smoke->inheritanceList + smokeClass->parents; if (*parent > 0) { type.BaseTypes.Add( new CodeTypeReference(ByteArrayManager.GetString((data.Smoke->classes + *parent)->className).Replace("::", "."))); } } if (Util.IsClassAbstract(data.Smoke, classId)) { type.TypeAttributes |= TypeAttributes.Abstract; } if (PreMembersHooks != null) { PreMembersHooks(data.Smoke, smokeClass, type); } if (!alreadyDefined) { DefineWrapperClassFieldsAndMethods(smokeClass, type); data.CSharpTypeMap[mapName] = type; IList collection = data.GetTypeCollection(prefix); collection.Add(type); type.UserData.Add("parent", prefix); // add the internal implementation type for abstract classes if ((type.TypeAttributes & TypeAttributes.Abstract) == TypeAttributes.Abstract) { CodeTypeDeclaration implType = new CodeTypeDeclaration(); implType.Name = type.Name + "Internal"; implType.BaseTypes.Add(new CodeTypeReference(type.Name)); implType.IsPartial = true; implType.TypeAttributes = TypeAttributes.NotPublic; CodeConstructor dummyCtor = new CodeConstructor(); dummyCtor.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(Type)), "dummy")); dummyCtor.BaseConstructorArgs.Add(new CodeSnippetExpression("(System.Type) null")); dummyCtor.Attributes = MemberAttributes.Family; implType.Members.Add(dummyCtor); data.InternalTypeMap[type] = implType; collection.Add(implType); } } data.SmokeTypeMap[(IntPtr)smokeClass] = type; }
public void Run() { HashSet <short> interfaceClasses = GetClassList(); // Make the interfaces known first, otherwise Translator won't work correctly. foreach (short idx in interfaceClasses) { Smoke.Class *klass = data.Smoke->classes + idx; string className = ByteArrayManager.GetString(klass->className); int colon = className.LastIndexOf("::", StringComparison.Ordinal); string prefix = (colon != -1) ? className.Substring(0, colon) : string.Empty; string name = (colon != -1) ? className.Substring(colon + 2) : className; CodeTypeDeclaration ifaceDecl = new CodeTypeDeclaration('I' + name); ifaceDecl.IsInterface = true; CodeAttributeDeclaration attr = new CodeAttributeDeclaration("SmokeClass", new CodeAttributeArgument( new CodePrimitiveExpression(className))); ifaceDecl.CustomAttributes.Add(attr); data.GetTypeCollection(prefix).Add(ifaceDecl); data.InterfaceTypeMap[className] = ifaceDecl; } // Now generate the methods. foreach (short idx in interfaceClasses) { Smoke.Class * klass = data.Smoke->classes + idx; string className = ByteArrayManager.GetString(klass->className); CodeTypeDeclaration ifaceDecl = data.InterfaceTypeMap[className]; short *parent = data.Smoke->inheritanceList + klass->parents; while (*parent > 0) { ifaceDecl.BaseTypes.Add(translator.CppToCSharp(data.Smoke->classes + *parent)); parent++; } MethodsGenerator mg = new MethodsGenerator(data, translator, ifaceDecl, klass); AttributeGenerator ag = new AttributeGenerator(data, translator, ifaceDecl); List <IntPtr> methods = new List <IntPtr>(); ///TODO: replace this algorithm, it's highly inefficient for (short i = 0; i <= data.Smoke->numMethods && data.Smoke->methods[i].classId <= idx; i++) { Smoke.Method *meth = data.Smoke->methods + i; if (meth->classId != idx) { continue; } string methName = ByteArrayManager.GetString(data.Smoke->methodNames[meth->name]); // we don't want anything except protected, const or empty flags if ((meth->flags & (ushort)Smoke.MethodFlags.mf_enum) > 0 || (meth->flags & (ushort)Smoke.MethodFlags.mf_ctor) > 0 || (meth->flags & (ushort)Smoke.MethodFlags.mf_copyctor) > 0 || (meth->flags & (ushort)Smoke.MethodFlags.mf_dtor) > 0 || (meth->flags & (ushort)Smoke.MethodFlags.mf_static) > 0 || (meth->flags & (ushort)Smoke.MethodFlags.mf_internal) > 0 || (meth->flags & (ushort)Smoke.MethodFlags.mf_protected) > 0 || methName.StartsWith("operator")) { continue; } if ((meth->flags & (ushort)Smoke.MethodFlags.mf_attribute) > 0) { ag.ScheduleAttributeAccessor(meth); continue; } methods.Add((IntPtr)meth); } methods.Sort(CompareSmokeMethods); foreach (Smoke.Method *method in methods) { CodeMemberMethod cmm = mg.GenerateBasicMethodDefinition(data.Smoke, method); if (cmm != null && !ifaceDecl.HasMethod(cmm)) { ifaceDecl.Members.Add(cmm); } } mg.GenerateProperties(); foreach (CodeMemberProperty prop in ag.GenerateBasicAttributeDefinitions()) { ifaceDecl.Members.Add(prop); } } }