コード例 #1
0
        void OutputClass(ClassDefinition c, int level)
        {
            EnsureHeaderWhiteSpace();
            EnsureSourceWhiteSpace();

            // Write access modifier
            WriteTabs(level);
            if (level == 1)
            {
                HeaderWrite("public ");
            }

            // Write class definition
            HeaderWrite("ref class ");
            HeaderWrite(c.ManagedName);
            if (c.IsAbstract)
            {
                HeaderWrite(" abstract");
            }
            if (c.BaseClass != null)
            {
                HeaderWrite(" : ");
                HeaderWriteLine(c.BaseClass.ManagedName);
            }
            else
            {
                if (c.IsTrackingDisposable)
                {
                    HeaderWriteLine(" : ITrackingDisposable");
                }
                else
                {
                    // In C++/CLI, IDisposable is inherited automatically if the destructor and finalizer are defined
                    //HeaderWriteLine(" : IDisposable");
                    if (c.IsStaticClass)
                    {
                        HeaderWrite(" sealed");
                    }
                    HeaderWriteLine();
                }
            }

            WriteTabs(level);
            HeaderWriteLine("{");
            //hasHeaderWhiteSpace = false;

            // Default access for ref class
            var currentAccess = RefAccessSpecifier.Private;

            // Write child classes
            if (c.Classes.Count != 0)
            {
                OutputClasses(c.Classes, ref currentAccess, level);
                currentAccess = RefAccessSpecifier.Public;
                SourceWriteLine();
            }

            // Classes without instances
            if (c.IsStaticClass)
            {
                EnsureAccess(level, ref currentAccess, RefAccessSpecifier.Private);
                WriteTabs(level + 1);
                HeaderWriteLine(string.Format("{0}() {{}}", c.ManagedName));
            }

            // Downcast native pointer if any methods in a derived class use it
            if (c.BaseClass != null && c.Methods.Any(m => !m.IsConstructor && !m.IsStatic))
            {
                EnsureSourceWhiteSpace();
                SourceWriteLine(string.Format("#define Native static_cast<{0}*>(_native)", c.FullName));
                hasSourceWhiteSpace = false;
            }

            // Write the unmanaged pointer to the base class
            if (c.BaseClass == null && !c.IsStaticClass)
            {
                if (c.Classes.Count != 0)
                {
                    HeaderWriteLine();
                }
                if (c.IsTrackingDisposable)
                {
                    EnsureAccess(level, ref currentAccess, RefAccessSpecifier.Public);
                    WriteTabs(level + 1);
                    HeaderWriteLine("virtual event EventHandler^ OnDisposing;");
                    WriteTabs(level + 1);
                    HeaderWriteLine("virtual event EventHandler^ OnDisposed;");
                    hasHeaderWhiteSpace = false;
                }
                EnsureAccess(level, ref currentAccess, RefAccessSpecifier.Internal);

                WriteTabs(level + 1);
                HeaderWrite(c.FullName);
                HeaderWriteLine("* _native;");
                hasHeaderWhiteSpace = false;
            }

            EnsureHeaderWhiteSpace();
            EnsureSourceWhiteSpace();

            // Private fields
            // _isDisposed flag
            if (c.IsTrackingDisposable)
            {
                EnsureAccess(level, ref currentAccess, RefAccessSpecifier.Private);
                WriteTabs(level + 1);
                HeaderWriteLine("bool _isDisposed;");
                hasHeaderWhiteSpace = false;
            }
            // _preventDelete flag
            if (c.HasPreventDelete)
            {
                EnsureAccess(level, ref currentAccess, RefAccessSpecifier.Private);
                WriteTabs(level + 1);
                HeaderWriteLine("bool _preventDelete;");
                hasHeaderWhiteSpace = false;
            }

            // Write unmanaged constructor
            // TODO: Write constructor from unmanaged pointer only if the class is ever instantiated in this way.
            if (!c.NoInternalConstructor && !c.IsStaticClass)
            {
                EnsureAccess(level, ref currentAccess, RefAccessSpecifier.Internal);

                WriteTabs(level + 1);
                SourceWrite(c.FullNameManaged);
                SourceWrite("::");
                Write(c.ManagedName);
                Write('(');
                Write(c.FullName);
                Write("* native)");
                HeaderWriteLine(';');
                SourceWriteLine();
                if (c.BaseClass != null)
                {
                    WriteTabs(1, true);
                    SourceWrite(": ");
                    SourceWrite(c.BaseClass.ManagedName);
                    SourceWriteLine("(native)");
                }
                SourceWriteLine('{');
                if (c.BaseClass == null)
                {
                    WriteTabs(1, true);
                    SourceWriteLine("_native = native;");
                }
                SourceWriteLine('}');
                hasHeaderWhiteSpace = false;
                hasSourceWhiteSpace = false;
            }

            // Write destructor & finalizer
            if (c.BaseClass == null && !c.IsStaticClass)
            {
                EnsureAccess(level, ref currentAccess, RefAccessSpecifier.Public);
                WriteTabs(level + 1);
                HeaderWriteLine(string.Format("!{0}();", c.ManagedName));
                EnsureAccess(level, ref currentAccess, RefAccessSpecifier.Protected);
                WriteTabs(level + 1);
                HeaderWriteLine(string.Format("~{0}();", c.ManagedName));
                hasHeaderWhiteSpace = false;

                EnsureSourceWhiteSpace();
                SourceWriteLine(string.Format("{0}::~{1}()", c.FullNameManaged, c.ManagedName));
                SourceWriteLine('{');
                SourceWriteLine(string.Format("\tthis->!{0}();", c.ManagedName));
                SourceWriteLine('}');
                SourceWriteLine();

                SourceWriteLine(string.Format("{0}::!{1}()", c.FullNameManaged, c.ManagedName));
                SourceWriteLine('{');
                if (c.IsTrackingDisposable)
                {
                    SourceWriteLine("\tif (this->IsDisposed)");
                    SourceWriteLine("\t\treturn;");
                    SourceWriteLine();
                    SourceWriteLine("\tOnDisposing(this, nullptr);");
                    SourceWriteLine();
                }
                if (c.HasPreventDelete)
                {
                    SourceWriteLine("\tif (!_preventDelete)");
                    SourceWriteLine("\t{");
                    SourceWriteLine("\t\tdelete _native;");
                    SourceWriteLine("\t}");
                }
                else
                {
                    SourceWriteLine("\tdelete _native;");
                }
                if (c.IsTrackingDisposable)
                {
                    SourceWriteLine("\t_isDisposed = true;");
                    SourceWriteLine();
                    SourceWriteLine("\tOnDisposed(this, nullptr);");
                }
                else
                {
                    SourceWriteLine("\t_native = NULL;");
                }
                SourceWriteLine('}');
                hasSourceWhiteSpace = false;
            }

            // Write constructors
            int constructorCount = 0;

            foreach (MethodDefinition method in c.Methods.Where(m => m.IsConstructor))
            {
                if (!c.HidePublicConstructors)
                {
                    EnsureAccess(level, ref currentAccess, RefAccessSpecifier.Public);
                    OutputMethod(method, level);
                }
                constructorCount++;
            }

            // Write default constructor
            if (constructorCount == 0 && !c.IsAbstract && !c.HidePublicConstructors && !c.IsStaticClass)
            {
                EnsureAccess(level, ref currentAccess, RefAccessSpecifier.Public);

                MethodDefinition constructor = new MethodDefinition(c.Name, c, 0);
                constructor.IsConstructor = true;
                OutputMethod(constructor, level);
                constructorCount++;
            }

            // Write methods
            if (c.Methods.Count - constructorCount != 0)
            {
                EnsureHeaderWhiteSpace();

                foreach (MethodDefinition method in c.Methods)
                {
                    if (!method.IsConstructor && method.Property == null)
                    {
                        EnsureAccess(level, ref currentAccess, RefAccessSpecifier.Public);
                        OutputMethod(method, level);
                    }
                }
            }

            // Write properties (includes unmanaged fields and getters/setters)
            foreach (PropertyDefinition prop in c.Properties)
            {
                string typeConditional = GetTypeConditional(prop.Type, c.Header);
                if (typeConditional != null)
                {
                    Write("#ifndef ");
                    WriteLine(typeConditional);
                    hasSourceWhiteSpace = true;
                }
                else
                {
                    EnsureHeaderWhiteSpace();
                }

                EnsureAccess(level, ref currentAccess, RefAccessSpecifier.Public);

                string typeRefName = BulletParser.GetTypeRefName(prop.Type);

                WriteTabs(level + 1);
                HeaderWrite("property ");
                HeaderWrite(typeRefName);
                HeaderWrite(" ");
                HeaderWriteLine(prop.Name);
                WriteTabs(level + 1);
                HeaderWriteLine("{");

                // Getter/Setter
                OutputMethod(prop.Getter, level + 1);
                if (prop.Setter != null)
                {
                    OutputMethod(prop.Setter, level + 1);
                }

                WriteTabs(level + 1);
                HeaderWriteLine("}");

                if (typeConditional != null)
                {
                    WriteLine("#endif");
                    hasSourceWhiteSpace = false;
                }

                hasHeaderWhiteSpace = false;
            }

            WriteTabs(level);
            HeaderWriteLine("};");
            hasHeaderWhiteSpace = false;
        }
コード例 #2
0
        void OutputMethod(MethodDefinition method, int level, int numOptionalParams = 0)
        {
            var parentClass = method.Parent;

            // No whitespace between get/set methods
            if (!(method.Property != null &&
                  method.Equals(method.Property.Setter)))
            {
                EnsureSourceWhiteSpace();
                hasHeaderWhiteSpace = false;
            }

            // #ifndef DISABLE_FEATURE
            bool hasConditional = false;

            if (method.Property == null)
            {
                foreach (var param in method.Parameters)
                {
                    string typeConditional = GetTypeConditional(param.Type, parentClass.Header);
                    if (typeConditional != null)
                    {
                        Write("#ifndef ");
                        WriteLine(typeConditional);
                        hasSourceWhiteSpace = true;
                        hasConditional      = true;
                    }
                }
            }

            WriteTabs(level + 1);

            // "static"
            if (method.IsStatic)
            {
                HeaderWrite("static ");
            }

            // Definition: return type
            if (!method.IsConstructor)
            {
                var returnType = method.ReturnType;

                if (method.Property != null)
                {
                    if (method.Equals(method.Property.Getter))
                    {
                        // If property name matches type name, resolve ambiguity
                        if (method.Property.Name.Equals(method.Property.Type.ManagedName))
                        {
                            HeaderWrite(NamespaceName + "::");
                        }

                        // Getter with parameter for return value
                        if (method.Parameters.Length == 1)
                        {
                            returnType = method.Parameters[0].Type;
                        }
                    }
                }

                Write(BulletParser.GetTypeRefName(returnType));
                Write(' ');
            }

            // Definition: name
            SourceWrite(parentClass.FullNameManaged);
            SourceWrite("::");
            if (method.IsConstructor)
            {
                Write(parentClass.ManagedName);
            }
            else
            {
                if (method.Property != null)
                {
                    SourceWrite(method.Property.Name);
                    SourceWrite("::");
                    if (method.Property.Getter.Equals(method))
                    {
                        Write("get");
                    }
                    else
                    {
                        Write("set");
                    }
                }
                else
                {
                    Write(method.ManagedName);
                }
            }
            Write('(');

            // Definition: parameters
            int numParameters = method.Parameters.Length - numOptionalParams;

            // Getters with parameter for return value
            if (numParameters == 1 && method.Property != null && method.Equals(method.Property.Getter))
            {
                numParameters = 0;
            }
            bool hasOptionalParam = false;

            for (int i = 0; i < numParameters; i++)
            {
                var param = method.Parameters[i];
                Write(BulletParser.GetTypeRefName(param.Type));
                Write(' ');
                Write(param.ManagedName);

                if (param.IsOptional)
                {
                    hasOptionalParam = true;
                }

                if (i != numParameters - 1)
                {
                    if (_headerLineLength >= LineBreakWidth)
                    {
                        HeaderWriteLine(",");
                        WriteTabs(level + 2);
                    }
                    else
                    {
                        HeaderWrite(", ");
                    }

                    if (_sourceLineLength >= LineBreakWidth)
                    {
                        SourceWriteLine(",");
                        WriteTabs(1, true);
                    }
                    else
                    {
                        SourceWrite(", ");
                    }
                }
            }
            HeaderWriteLine(");");
            SourceWriteLine(')');


            // Constructor chaining
            bool doConstructorChaining = false;

            if (method.IsConstructor && parentClass.BaseClass != null)
            {
                // If there is no need for marshalling code, we can chain constructors
                doConstructorChaining = true;
                foreach (var param in method.Parameters)
                {
                    if (BulletParser.TypeRequiresMarshal(param.Type))
                    {
                        doConstructorChaining = false;
                        break;
                    }
                }

                WriteTabs(1, true);
                SourceWrite(": ");
                SourceWrite(parentClass.BaseClass.ManagedName);
                SourceWrite('(');

                if (doConstructorChaining)
                {
                    SourceWrite("new ");
                    OutputMethodMarshal(method, numParameters);
                    if (parentClass.BaseClass.Target.HasPreventDelete)
                    {
                        SourceWrite(", false");
                    }
                }
                else
                {
                    SourceWrite('0');
                }

                SourceWriteLine(')');
            }

            // Method definition
            SourceWriteLine('{');

            if (!doConstructorChaining)
            {
                // Type marshalling prologue
                bool needTypeMarshalEpilogue = false;
                if (method.Field == null)
                {
                    for (int i = 0; i < numParameters; i++)
                    {
                        var    param    = method.Parameters[i];
                        string prologue = BulletParser.GetTypeMarshalPrologueCppCli(param);
                        if (!string.IsNullOrEmpty(prologue))
                        {
                            WriteTabs(1, true);
                            SourceWriteLine(prologue);
                        }

                        // Do we need a type marshalling epilogue?
                        if (!needTypeMarshalEpilogue)
                        {
                            string epilogue = BulletParser.GetTypeMarshalEpilogueCppCli(param);
                            if (!string.IsNullOrEmpty(epilogue))
                            {
                                needTypeMarshalEpilogue = true;
                            }
                        }
                    }
                }

                WriteTabs(1, true);
                if (method.IsConstructor)
                {
                    SourceWrite("_native = new ");
                }
                else
                {
                    if (!method.IsVoid)
                    {
                        //if (method.ReturnType.IsBasic || method.ReturnType.Referenced != null)
                        if (needTypeMarshalEpilogue)
                        {
                            // Return after epilogue (cleanup)
                            SourceWrite(BulletParser.GetTypeRefName(method.ReturnType));
                            SourceWrite(" ret = ");
                        }
                        else
                        {
                            // Return immediately
                            SourceWrite("return ");
                        }
                        SourceWrite(BulletParser.GetTypeMarshalConstructorStart(method));
                    }
                    else
                    {
                        if (method.Property != null && method.Equals(method.Property.Getter))
                        {
                            SourceWrite(BulletParser.GetTypeMarshalConstructorStart(method));
                        }
                    }
                }

                // Native is defined as static_cast<className*>(_native)
                string nativePointer = (parentClass.BaseClass != null) ? "Native" : "_native";

                if (method.Field != null)
                {
                    if (method.Equals(method.Property.Getter))
                    {
                        SourceWrite(nativePointer);
                        SourceWrite("->");
                        SourceWrite(method.Field.Name);
                    }

                    var setter = method.Property.Setter;
                    if (setter != null && method.Equals(setter))
                    {
                        var param    = method.Parameters[0];
                        var fieldSet = BulletParser.GetTypeMarshalFieldSetCppCli(method.Field, param, nativePointer);
                        if (!string.IsNullOrEmpty(fieldSet))
                        {
                            SourceWrite(fieldSet);
                        }
                        else
                        {
                            SourceWrite(string.Format("{0}->{1} = ", nativePointer, method.Field.Name));
                            if (param.Type.IsPointer || param.Type.IsReference)
                            {
                                if (param.Type.IsReference)
                                {
                                    // Dereference
                                    SourceWrite('*');
                                }

                                if (param.Type.Referenced.Target != null &&
                                    param.Type.Referenced.Target.BaseClass != null)
                                {
                                    // Cast native pointer from base class
                                    SourceWrite(string.Format("({0}*)", param.Type.Referenced.FullName));
                                }
                            }
                            SourceWrite(param.ManagedName);
                            if (!param.Type.IsBasic)
                            {
                                SourceWrite("->_native");
                            }
                        }
                    }
                }
                else
                {
                    if (!method.IsConstructor)
                    {
                        if (method.IsStatic)
                        {
                            SourceWrite(parentClass.FullName);
                            SourceWrite("::");
                        }
                        else
                        {
                            SourceWrite(nativePointer);
                            SourceWrite("->");
                        }
                    }
                    OutputMethodMarshal(method, numParameters);
                }
                if (!method.IsConstructor && !method.IsVoid)
                {
                    SourceWrite(BulletParser.GetTypeMarshalConstructorEnd(method));
                }
                SourceWriteLine(';');

                // Write type marshalling epilogue
                if (needTypeMarshalEpilogue)
                {
                    for (int i = 0; i < numParameters; i++)
                    {
                        var    param    = method.Parameters[i];
                        string epilogue = BulletParser.GetTypeMarshalEpilogueCppCli(param);
                        if (!string.IsNullOrEmpty(epilogue))
                        {
                            WriteTabs(1, true);
                            SourceWriteLine(epilogue);
                        }
                    }
                    if (!method.IsVoid)
                    {
                        WriteTabs(1, true);
                        SourceWriteLine("return ret;");
                    }
                }
            }
            SourceWriteLine('}');
            hasSourceWhiteSpace = false;

            // #endif // DISABLE_FEATURE
            if (hasConditional)
            {
                foreach (var param in method.Parameters)
                {
                    string typeConditional = GetTypeConditional(param.Type, method.Parent.Header);
                    if (typeConditional != null)
                    {
                        WriteLine("#endif");
                        hasHeaderWhiteSpace = true;
                    }
                }
            }

            // If there are optional parameters, then output all possible combinations of calls
            if (hasOptionalParam)
            {
                OutputMethod(method, level, numOptionalParams + 1);
            }
        }
コード例 #3
0
        void OutputMethod(MethodDefinition method, int level, int numOptionalParams = 0)
        {
            var parentClass = method.Parent;

            // No whitespace between get/set methods
            if (!(method.Property != null &&
                  method.Equals(method.Property.Setter)))
            {
                EnsureSourceWhiteSpace();
                hasHeaderWhiteSpace = false;
            }

            // #ifndef DISABLE_FEATURE
            bool hasConditional = false;

            if (method.Property == null)
            {
                foreach (var param in method.Parameters)
                {
                    string typeConditional = GetTypeConditional(param.Type, parentClass.Header);
                    if (typeConditional != null)
                    {
                        WriteLine(string.Format("#ifndef {0}", typeConditional));
                        hasSourceWhiteSpace = true;
                        hasConditional      = true;
                    }
                }
            }

            WriteTabs(level + 1);

            // "static"
            if (method.IsStatic)
            {
                HeaderWrite("static ");
            }

            // Definition: return type
            if (!method.IsConstructor)
            {
                var returnType = method.ReturnType;

                if (method.Property != null)
                {
                    if (method.Equals(method.Property.Getter))
                    {
                        // If property name matches type name, resolve ambiguity
                        if (method.Property.Name.Equals(method.Property.Type.ManagedName))
                        {
                            HeaderWrite(NamespaceName + "::");
                        }

                        // Getter with parameter for return value
                        if (method.Parameters.Length == 1)
                        {
                            returnType = method.Parameters[0].Type;
                        }
                    }
                }

                Write(BulletParser.GetTypeRefName(returnType));
                Write(' ');
            }

            // Definition: name
            string headerMethodName;
            string sourceMethodName;

            if (method.IsConstructor)
            {
                headerMethodName = parentClass.ManagedName;
                sourceMethodName = headerMethodName;
            }
            else if (method.Property != null)
            {
                headerMethodName = method.Property.Getter.Equals(method) ? "get" : "set";
                sourceMethodName = string.Format("{0}::{1}", method.Property.Name, headerMethodName);
            }
            else
            {
                headerMethodName = method.ManagedName;
                sourceMethodName = headerMethodName;
            }
            HeaderWrite(string.Format("{0}(", headerMethodName));
            SourceWrite(string.Format("{0}::{1}(", parentClass.FullNameManaged, sourceMethodName));

            // Definition: parameters
            int numParameters = method.Parameters.Length - numOptionalParams;

            // Getters with parameter for return value
            if (numParameters == 1 && method.Property != null && method.Equals(method.Property.Getter))
            {
                numParameters = 0;
            }
            bool hasOptionalParam = false;

            for (int i = 0; i < numParameters; i++)
            {
                var param = method.Parameters[i];
                Write(string.Format("{0} {1}",
                                    BulletParser.GetTypeRefName(param.Type), param.ManagedName));

                if (param.IsOptional)
                {
                    hasOptionalParam = true;
                }

                if (i != numParameters - 1)
                {
                    if (_headerLineLength >= LineBreakWidth)
                    {
                        HeaderWriteLine(",");
                        WriteTabs(level + 2);
                    }
                    else
                    {
                        HeaderWrite(", ");
                    }

                    if (_sourceLineLength >= LineBreakWidth)
                    {
                        SourceWriteLine(",");
                        WriteTabs(1, true);
                    }
                    else
                    {
                        SourceWrite(", ");
                    }
                }
            }
            HeaderWriteLine(");");
            SourceWriteLine(')');


            // Constructor chaining
            bool doConstructorChaining = false;

            if (method.IsConstructor && parentClass.BaseClass != null)
            {
                // If there is no need for marshalling code, we can chain constructors
                doConstructorChaining = method.Parameters.All(p => !BulletParser.TypeRequiresMarshal(p.Type));

                WriteTabs(1, true);
                SourceWrite(string.Format(": {0}(", parentClass.BaseClass.ManagedName));

                if (doConstructorChaining)
                {
                    SourceWrite("new ");
                    OutputMethodMarshal(method, numParameters);
                    if (parentClass.BaseClass.HasPreventDelete)
                    {
                        SourceWrite(", false");
                    }
                }
                else
                {
                    SourceWrite('0');
                }

                SourceWriteLine(')');
            }

            // Method definition
            SourceWriteLine('{');
            if (!doConstructorChaining)
            {
                WriteMethodDefinition(method, numParameters);
            }
            // Cache property values
            if (method.IsConstructor)
            {
                var assignments  = new List <string>();
                var methodParent = method.Parent;
                while (methodParent != null)
                {
                    foreach (var cachedProperty in methodParent.CachedProperties.OrderBy(p => p.Key))
                    {
                        foreach (var param in method.Parameters)
                        {
                            if (param.ManagedName.ToLower() == cachedProperty.Key.ToLower() &&
                                param.Type.ManagedName == cachedProperty.Value.Property.Type.ManagedName)
                            {
                                string assignment = string.Format("\t{0} = {1};", cachedProperty.Value.CacheFieldName, param.ManagedName);
                                assignments.Add(assignment);
                            }
                        }
                    }
                    methodParent = methodParent.BaseClass;
                }
                if (assignments.Count != 0)
                {
                    EnsureSourceWhiteSpace();
                    foreach (string assignment in assignments)
                    {
                        SourceWriteLine(assignment);
                    }
                    hasSourceWhiteSpace = false;
                }
            }
            SourceWriteLine('}');
            hasSourceWhiteSpace = false;

            // #endif // DISABLE_FEATURE
            if (hasConditional)
            {
                foreach (var param in method.Parameters)
                {
                    string typeConditional = GetTypeConditional(param.Type, method.Parent.Header);
                    if (typeConditional != null)
                    {
                        WriteLine("#endif");
                        hasHeaderWhiteSpace = true;
                    }
                }
            }

            // If there are optional parameters, then output all possible combinations of calls
            if (hasOptionalParam)
            {
                OutputMethod(method, level, numOptionalParams + 1);
            }
        }
コード例 #4
0
        void OutputClass(ClassDefinition @class, int level)
        {
            EnsureHeaderWhiteSpace();
            EnsureSourceWhiteSpace();

            // Write access modifier
            WriteTabs(level);
            if (level == 1)
            {
                HeaderWrite("public ");
            }

            // Write class definition
            HeaderWrite(string.Format("ref class {0}", @class.ManagedName));
            if (@class.IsAbstract)
            {
                HeaderWrite(" abstract");
            }
            else if (@class.IsStaticClass)
            {
                HeaderWrite(" sealed");
            }
            if (@class.BaseClass != null)
            {
                HeaderWriteLine(string.Format(" : {0}", @class.BaseClass.ManagedName));
            }
            else if (@class.IsTrackingDisposable)
            {
                HeaderWriteLine(" : ITrackingDisposable");
            }
            else
            {
                // In C++/CLI, IDisposable is inherited automatically if the destructor and finalizer are defined
                //HeaderWrite(" : IDisposable");
                HeaderWriteLine();
            }

            WriteTabs(level);
            HeaderWriteLine("{");
            //hasHeaderWhiteSpace = true;

            // Default access for ref class
            var currentAccess = RefAccessSpecifier.Private;

            // Write child classes
            if ([email protected](cl => IsExcludedClass(cl)))
            {
                OutputClasses(@class.Classes, ref currentAccess, level);
                currentAccess = RefAccessSpecifier.Public;
                SourceWriteLine();
            }

            // Add a private constructor for classes without instances
            if (@class.IsStaticClass)
            {
                EnsureAccess(level, ref currentAccess, RefAccessSpecifier.Private);
                WriteTabs(level + 1);
                HeaderWriteLine(string.Format("{0}() {{}}", @class.ManagedName));
                hasHeaderWhiteSpace = false;
            }

            // Downcast native pointer if any methods in a derived class use it
            if (@class.BaseClass != null && @class.Methods.Any(m => !m.IsConstructor && !m.IsStatic))
            {
                EnsureSourceWhiteSpace();
                SourceWriteLine(string.Format("#define Native static_cast<{0}*>(_native)", @class.FullyQualifiedName));
                hasSourceWhiteSpace = false;
            }

            // Write the native pointer to the base class
            if (@class.BaseClass == null && [email protected])
            {
                if (@class.Classes.Any(c => !IsExcludedClass(c)))
                {
                    HeaderWriteLine();
                }
                if (@class.IsTrackingDisposable)
                {
                    EnsureAccess(level, ref currentAccess, RefAccessSpecifier.Public);
                    WriteTabs(level + 1);
                    HeaderWriteLine("virtual event EventHandler^ OnDisposing;");
                    WriteTabs(level + 1);
                    HeaderWriteLine("virtual event EventHandler^ OnDisposed;");
                    hasHeaderWhiteSpace = false;
                }
                EnsureAccess(level, ref currentAccess, RefAccessSpecifier.Internal);

                WriteTabs(level + 1);
                HeaderWrite(@class.FullyQualifiedName);
                HeaderWriteLine("* _native;");
                hasHeaderWhiteSpace = false;
            }

            EnsureHeaderWhiteSpace();
            EnsureSourceWhiteSpace();

            // Private fields
            // _isDisposed flag
            if (@class.IsTrackingDisposable)
            {
                EnsureAccess(level, ref currentAccess, RefAccessSpecifier.Private);
                WriteTabs(level + 1);
                HeaderWriteLine("bool _isDisposed;");
                hasHeaderWhiteSpace = false;
            }
            // _preventDelete flag
            if (@class.HasPreventDelete)
            {
                EnsureAccess(level, ref currentAccess, RefAccessSpecifier.Private);
                WriteTabs(level + 1);
                HeaderWriteLine("bool _preventDelete;");
                hasHeaderWhiteSpace = false;
            }

            // Write cached property fields
            foreach (var cachedProperty in @class.CachedProperties.OrderBy(p => p.Key))
            {
                EnsureAccess(level, ref currentAccess, cachedProperty.Value.Access);
                WriteTabs(level + 1);
                string name = cachedProperty.Key;
                name = char.ToLower(name[0]) + name.Substring(1);
                HeaderWriteLine(string.Format("{0} _{1};",
                                              BulletParser.GetTypeRefName(cachedProperty.Value.Property.Type), name));
                hasHeaderWhiteSpace = false;
            }

            // Write constructors and destructors if not static
            if ([email protected])
            {
                // Write unmanaged constructor
                // TODO: Write constructor from unmanaged pointer only if the class is ever instantiated in this way.
                if ([email protected])
                {
                    EnsureAccess(level, ref currentAccess, RefAccessSpecifier.Internal);

                    WriteTabs(level + 1);
                    SourceWrite(string.Format("{0}::", @class.FullNameManaged));
                    Write(string.Format("{0}({1}* native)", @class.ManagedName, @class.FullyQualifiedName));
                    HeaderWriteLine(';');
                    SourceWriteLine();
                    if (@class.BaseClass != null)
                    {
                        WriteTabs(1, true);
                        SourceWriteLine(string.Format(": {0}(native)", @class.BaseClass.ManagedName));
                    }
                    SourceWriteLine('{');
                    if (@class.BaseClass == null)
                    {
                        WriteTabs(1, true);
                        SourceWriteLine("_native = native;");
                    }
                    SourceWriteLine('}');
                    hasHeaderWhiteSpace = false;
                    hasSourceWhiteSpace = false;
                }

                // Write destructor & finalizer
                if (@class.BaseClass == null)
                {
                    // ECMA-372 19.13.2: "The access-specifier of a finalizer in a ref class is ignored."
                    WriteTabs(level + 1);
                    HeaderWriteLine(string.Format("!{0}();", @class.ManagedName));
                    // ECMA-372 19.13.1: "The access-specifier of a destructor in a ref class is ignored."
                    WriteTabs(level + 1);
                    HeaderWriteLine(string.Format("~{0}();", @class.ManagedName));
                    hasHeaderWhiteSpace = false;

                    EnsureSourceWhiteSpace();
                    SourceWriteLine(string.Format("{0}::~{1}()", @class.FullNameManaged, @class.ManagedName));
                    SourceWriteLine('{');
                    SourceWriteLine(string.Format("\tthis->!{0}();", @class.ManagedName));
                    SourceWriteLine('}');
                    SourceWriteLine();

                    SourceWriteLine(string.Format("{0}::!{1}()", @class.FullNameManaged, @class.ManagedName));
                    SourceWriteLine('{');
                    if (@class.IsTrackingDisposable)
                    {
                        SourceWriteLine("\tif (this->IsDisposed)");
                        SourceWriteLine("\t\treturn;");
                        SourceWriteLine();
                        SourceWriteLine("\tOnDisposing(this, nullptr);");
                        SourceWriteLine();
                    }
                    if (@class.HasPreventDelete)
                    {
                        SourceWriteLine("\tif (!_preventDelete)");
                        SourceWriteLine("\t{");
                        SourceWriteLine("\t\tdelete _native;");
                        SourceWriteLine("\t}");
                    }
                    else
                    {
                        SourceWriteLine("\tdelete _native;");
                    }
                    if (@class.IsTrackingDisposable)
                    {
                        SourceWriteLine("\t_isDisposed = true;");
                        SourceWriteLine();
                        SourceWriteLine("\tOnDisposed(this, nullptr);");
                    }
                    else
                    {
                        SourceWriteLine("\t_native = NULL;");
                    }
                    SourceWriteLine('}');
                    hasSourceWhiteSpace = false;
                }

                // Write public constructors
                if ([email protected] && [email protected])
                {
                    EnsureAccess(level, ref currentAccess, RefAccessSpecifier.Public);

                    var constructors = @class.Methods.Where(m => m.IsConstructor);
                    if (constructors.Any())
                    {
                        foreach (var constructor in constructors)
                        {
                            OutputMethod(constructor, level);
                        }
                    }
                    else
                    {
                        // Default constructor
                        MethodDefinition constructor = new MethodDefinition(@class.Name, @class, 0);
                        constructor.IsConstructor = true;
                        OutputMethod(constructor, level);
                    }
                }
            }

            // Write non-constructor methods
            var methods = @class.Methods.Where(m => !m.IsConstructor);

            if (methods.Any())
            {
                EnsureHeaderWhiteSpace();

                foreach (var method in methods)
                {
                    if (method.Property != null)
                    {
                        continue;
                    }

                    EnsureAccess(level, ref currentAccess, RefAccessSpecifier.Public);
                    OutputMethod(method, level);
                }
            }

            // Write properties (includes unmanaged fields and getters/setters)
            foreach (PropertyDefinition prop in @class.Properties)
            {
                string typeConditional = GetTypeConditional(prop.Type, @class.Header);
                if (typeConditional != null)
                {
                    WriteLine(string.Format("#ifndef {0}", typeConditional));
                    hasSourceWhiteSpace = true;
                }
                else
                {
                    EnsureHeaderWhiteSpace();
                }

                EnsureAccess(level, ref currentAccess, RefAccessSpecifier.Public);

                WriteTabs(level + 1);
                HeaderWriteLine(string.Format("property {0} {1}",
                                              BulletParser.GetTypeRefName(prop.Type), prop.Name));
                WriteTabs(level + 1);
                HeaderWriteLine("{");

                // Getter/Setter
                OutputMethod(prop.Getter, level + 1);
                if (prop.Setter != null)
                {
                    OutputMethod(prop.Setter, level + 1);
                }

                WriteTabs(level + 1);
                HeaderWriteLine("}");

                if (typeConditional != null)
                {
                    WriteLine("#endif");
                    hasSourceWhiteSpace = false;
                }

                hasHeaderWhiteSpace = false;
            }

            WriteTabs(level);
            HeaderWriteLine("};");
            hasHeaderWhiteSpace = false;
        }
コード例 #5
0
        void WriteMethodDefinition(MethodDefinition method, int numParameters)
        {
            var parentClass = method.Parent;

            // Type marshalling prologue
            bool needTypeMarshalEpilogue = false;

            if (method.Field == null)
            {
                foreach (var param in method.Parameters)
                {
                    string prologue = BulletParser.GetTypeMarshalPrologueCppCli(param);
                    if (!string.IsNullOrEmpty(prologue))
                    {
                        WriteTabs(1, true);
                        SourceWriteLine(prologue);
                    }

                    // Do we need a type marshalling epilogue?
                    if (!needTypeMarshalEpilogue)
                    {
                        string epilogue = BulletParser.GetTypeMarshalEpilogueCppCli(param);
                        if (!string.IsNullOrEmpty(epilogue))
                        {
                            needTypeMarshalEpilogue = true;
                        }
                    }
                }
            }

            WriteTabs(1, true);
            if (method.IsConstructor)
            {
                SourceWrite("_native = new ");
            }
            else if (!method.IsVoid)
            {
                //if (method.ReturnType.IsBasic || method.ReturnType.Referenced != null)
                if (needTypeMarshalEpilogue)
                {
                    // Return after epilogue (cleanup)
                    SourceWrite(string.Format("{0} ret = ",
                                              BulletParser.GetTypeRefName(method.ReturnType)));
                }
                else
                {
                    // Return immediately
                    SourceWrite("return ");
                }
                SourceWrite(BulletParser.GetTypeMarshalConstructorStart(method));
            }
            else if (method.Property != null && method.Equals(method.Property.Getter))
            {
                SourceWrite(BulletParser.GetTypeMarshalConstructorStart(method));
            }

            // Native is defined as static_cast<className*>(_native)
            string nativePointer = (parentClass.BaseClass != null) ? "Native" : "_native";

            if (method.Field != null)
            {
                var property = method.Property;
                if (method.Equals(property.Getter))
                {
                    CachedProperty cachedProperty;
                    if (method.Parent.CachedProperties.TryGetValue(property.Name, out cachedProperty))
                    {
                        SourceWrite(cachedProperty.CacheFieldName);
                    }
                    else
                    {
                        SourceWrite(string.Format("{0}->{1}", nativePointer, method.Field.Name));
                    }
                }
                else if (property.Setter != null && method.Equals(property.Setter))
                {
                    var param    = method.Parameters[0];
                    var fieldSet = BulletParser.GetTypeMarshalFieldSetCppCli(method.Field, param, nativePointer);
                    if (!string.IsNullOrEmpty(fieldSet))
                    {
                        SourceWrite(fieldSet);
                    }
                    else
                    {
                        SourceWrite(string.Format("{0}->{1} = ", nativePointer, method.Field.Name));
                        if (param.Type.IsPointer || param.Type.IsReference)
                        {
                            if (param.Type.IsReference)
                            {
                                // Dereference
                                SourceWrite('*');
                            }

                            if (param.Type.Referenced.Target != null &&
                                param.Type.Referenced.Target.BaseClass != null)
                            {
                                // Cast native pointer from base class
                                SourceWrite(string.Format("({0}*)", param.Type.Referenced.FullName));
                            }
                        }
                        SourceWrite(param.ManagedName);
                        if (!param.Type.IsBasic)
                        {
                            SourceWrite("->_native");
                        }
                    }
                }
            }
            else
            {
                if (method.IsConstructor)
                {
                }
                else if (method.IsStatic)
                {
                    SourceWrite(parentClass.FullyQualifiedName + "::");
                }
                else
                {
                    SourceWrite(nativePointer + "->");
                }
                OutputMethodMarshal(method, numParameters);
            }
            if (!method.IsConstructor && !method.IsVoid)
            {
                SourceWrite(BulletParser.GetTypeMarshalConstructorEnd(method));
            }
            SourceWriteLine(';');

            // Write type marshalling epilogue
            if (needTypeMarshalEpilogue)
            {
                foreach (var param in method.Parameters)
                {
                    string epilogue = BulletParser.GetTypeMarshalEpilogueCppCli(param);
                    if (!string.IsNullOrEmpty(epilogue))
                    {
                        WriteTabs(1, true);
                        SourceWriteLine(epilogue);
                    }
                }
                if (!method.IsVoid)
                {
                    WriteTabs(1, true);
                    SourceWriteLine("return ret;");
                }
            }
        }