// Property from getter method
        public PropertyDefinition(MethodDefinition getter)
        {
            Getter = getter;
            Parent = getter.Parent;
            Parent.Properties.Add(this);
            getter.Property = this;

            string name = getter.Name;

            // one_two_three -> oneTwoThree
            while (name.Contains("_"))
            {
                int pos = name.IndexOf('_');
                name = name.Substring(0, pos) + name.Substring(pos + 1, 1).ToUpper() + name.Substring(pos + 2);
            }

            if (name.StartsWith("get", StringComparison.InvariantCultureIgnoreCase))
            {
                Name = name.Substring(3);
            }
            else if (name.StartsWith("is", StringComparison.InvariantCultureIgnoreCase))
            {
                Name = name[0].ToString().ToUpper() + name.Substring(1);
            }
            else if (name.StartsWith("has", StringComparison.InvariantCultureIgnoreCase))
            {
                Name = name[0].ToString().ToUpper() + name.Substring(1);
            }
            else
            {
                throw new NotImplementedException();
            }
        }
Exemplo n.º 2
0
        private void WriteMethodDeclaration(MethodDefinition method, int numParameters, int level, int overloadIndex)
        {
            Write(1, "EXPORT ", WriteTo.Header);

            // Return type
            if (method.IsConstructor)
            {
                Write($"{GetFullNameC(method.Parent)}* ", WriteTo.Header | WriteTo.Source);
            }
            else if (method.OutValueParameter != null)
            {
                Write("void ", WriteTo.Header | WriteTo.Source);
            }
            else
            {
                Write($"{GetTypeNameC(method.ReturnType)} ", WriteTo.Header | WriteTo.Source);
            }


            // Name
            string methodName = method.IsConstructor ? "new" : method.Name;
            if (overloadIndex != 0)
            {
                methodName += (overloadIndex + 1).ToString();
            }
            Write($"{GetFullNameC(method.Parent)}_{methodName}(",
                WriteTo.Header | WriteTo.Source);


            // Parameters
            var parameters = method.Parameters.Take(numParameters);

            if (method.OutValueParameter != null) parameters = parameters.Concat(new[] {
                method.OutValueParameter
            });

            var parametersCpp = parameters.Select(p => $"{GetTypeNameC(p.Type)} {p.Name}");

            // The first parameter is the instance pointer (if not constructor or static method)
            if (!method.IsConstructor && !method.IsStatic)
            {
                parametersCpp =
                    new[] { $"{GetFullNameC(method.Parent)}* obj" }.Concat(parametersCpp);
            }

            WriteLine($"{string.Join(", ", parametersCpp)});", WriteTo.Header);
            WriteLine($"{ListToLines(parametersCpp, WriteTo.Source)})", WriteTo.Source);
        }
        public ManagedMethod(MethodDefinition nativeMethod, ManagedClass parent, string name)
        {
            Native = nativeMethod;
            Parent = parent;
            Name = name;

            Parameters = nativeMethod.Parameters.Select(p => new ManagedParameter(p)).ToArray();
            if (nativeMethod.OutValueParameter != null)
            {
                OutValueParameter = new ManagedParameter(nativeMethod.OutValueParameter);
            }

            if (parent != null)
            {
                parent.Methods.Add(this);
            }
        }
        bool MethodNeedsExtensions(MethodDefinition method)
        {
            // Extension constructors & static extension methods not supported
            if (method.IsConstructor || method.IsStatic)
            {
                return false;
            }

            foreach (var param in method.Parameters)
            {
                if (_extensionClassesInternal.ContainsKey(param.Type.ManagedName))
                {
                    return true;
                }
            }
            return false;
        }
 public MethodDefinition Copy(ClassDefinition parent = null)
 {
     var m = new MethodDefinition(Name, parent ?? Parent, Parameters.Length)
     {
         Access = Access,
         Field = Field,
         IsAbstract = IsAbstract,
         IsConstructor = IsConstructor,
         IsExcluded = IsExcluded,
         IsStatic = IsStatic,
         OutValueParameter = OutValueParameter?.Copy(),
         ReturnType = ReturnType.Copy()
     };
     for (int i = 0; i < Parameters.Length; i++)
     {
         m.Parameters[i] = Parameters[i].Copy();
     }
     return m;
 }
Exemplo n.º 6
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;
        }
        public MethodDefinition SpecializeTemplateMethod(ClassDefinition thisClass, MethodDefinition templateMethod,
            IDictionary<string, string> templateParams)
        {
            var methodSpec = templateMethod.Copy(thisClass);

            // Replace template parameters with concrete types
            methodSpec.ReturnType = CopyTypeTemplated(methodSpec.ReturnType, templateParams);
            foreach (var param in methodSpec.Parameters)
            {
                param.Type = CopyTypeTemplated(param.Type, templateParams);
            }

            return methodSpec;
        }
Exemplo n.º 8
0
        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);
            }
        }
Exemplo n.º 9
0
        void WriteClass(ClassDefinition c, int level)
        {
            if (c.IsExcluded || c.IsTypedef || c.IsPureEnum)
            {
                return;
            }

            if (wrapperHeaderGuards.ContainsKey(c.Name))
            {
                WriteClassWrapper(c);
            }

            EnsureWhiteSpace(WriteTo.Source | WriteTo.CS);

            // Write class definition
            WriteTabs(level, WriteTo.CS);
            Write("public class ", WriteTo.CS);
            Write(c.ManagedName, WriteTo.CS);
            if (c.BaseClass != null)
            {
                Write(" : ", WriteTo.CS);
                WriteLine(c.BaseClass.Target.FullNameManaged.Replace("::", "."), WriteTo.CS);
                //WriteLine(c.BaseClass.ManagedNameCS, WriteTo.CS);
            }
            else
            {
                WriteLine(" : IDisposable", WriteTo.CS);
            }
            WriteTabs(level, WriteTo.CS);
            WriteLine("{", WriteTo.CS);
            hasCSWhiteSpace = true;

            // Write child classes
            foreach (ClassDefinition cl in c.Classes.OrderBy(x => x.FullNameManaged))
            {
                WriteClass(cl, level + 1);
            }

            if (!hasClassSeparatingWhitespace)
            {
                WriteLine(WriteTo.Header | WriteTo.Source);
                hasClassSeparatingWhitespace = true;
            }

            // Write native pointer
            if (c.BaseClass == null)
            {
                EnsureWhiteSpace(WriteTo.CS);
                WriteTabs(level + 1, WriteTo.CS);
                WriteLine("internal IntPtr _native;", WriteTo.CS);
                if (c.HasPreventDelete)
                {
                    WriteTabs(level + 1, WriteTo.CS);
                    WriteLine("bool _preventDelete;", WriteTo.CS);
                    hasCSWhiteSpace = false;
                }
                hasCSWhiteSpace = false;
            }

            // Write methods
            int overloadIndex = 0;
            bufferBuilder.Clear();

            // Write C# internal constructor
            if (!c.NoInternalConstructor)
            {
                EnsureWhiteSpace(WriteTo.CS);
                WriteTabs(level + 1, WriteTo.CS);
                Write("internal ", WriteTo.CS);
                Write(c.ManagedName, WriteTo.CS);
                Write("(IntPtr native", WriteTo.CS);
                if (c.HasPreventDelete)
                {
                    Write(", bool preventDelete", WriteTo.CS);
                }
                WriteLine(')', WriteTo.CS);
                if (c.BaseClass != null)
                {
                    WriteTabs(level + 2, WriteTo.CS);
                    Write(": base(native", WriteTo.CS);
                    if (c.HasPreventDelete)
                    {
                        if (!c.BaseClass.Target.HasPreventDelete)
                        {
                            // Base class should also have preventDelete
                            //throw new NotImplementedException();
                        }
                        Write(", preventDelete", WriteTo.CS);
                    }
                    else
                    {
                        if (c.BaseClass.Target.HasPreventDelete)
                        {
                            Write(", true", WriteTo.CS);
                        }
                    }
                    WriteLine(')', WriteTo.CS);
                }
                WriteTabs(level + 1, WriteTo.CS);
                WriteLine('{', WriteTo.CS);
                if (c.BaseClass == null)
                {
                    WriteTabs(level + 2, WriteTo.CS);
                    WriteLine("_native = native;", WriteTo.CS);
                    if (c.HasPreventDelete)
                    {
                        WriteTabs(level + 2, WriteTo.CS);
                        WriteLine("_preventDelete = preventDelete;", WriteTo.CS);
                    }
                }
                WriteTabs(level + 1, WriteTo.CS);
                WriteLine('}', WriteTo.CS);
                hasCSWhiteSpace = false;
            }

            // Write constructors
            bool hasConstructors = false;
            if (!c.IsAbstract)
            {
                foreach (MethodDefinition method in c.Methods.Where(m => m.IsConstructor))
                {
                    if (!c.HidePublicConstructors)
                    {
                        WriteMethod(method, level, ref overloadIndex);
                    }
                    hasConstructors = true;
                }

                // Write default constructor
                if (!hasConstructors && !c.IsAbstract && !c.HidePublicConstructors)
                {
                    var constructor = new MethodDefinition(c.Name, c, 0);
                    constructor.IsConstructor = true;
                    WriteMethod(constructor, level, ref overloadIndex);
                }
                overloadIndex = 0;
            }

            // Write methods
            MethodDefinition previousMethod = null;
            foreach (MethodDefinition method in c.Methods.Where(m => !m.IsConstructor).OrderBy(m => m.Name))
            {
                if (previousMethod != null && previousMethod.Name != method.Name)
                {
                    overloadIndex = 0;
                }

                WriteMethod(method, level, ref overloadIndex);
                previousMethod = method;
            }
            overloadIndex = 0;

            // Write properties
            foreach (PropertyDefinition prop in c.Properties)
            {
                WriteProperty(prop, level);
            }

            // Write delete method
            if (c.BaseClass == null)
            {
                var del = new MethodDefinition("delete", c, 0);
                del.ReturnType = new TypeRefDefinition();
                WriteMethod(del, level, ref overloadIndex);
                c.Methods.Remove(del);
                overloadIndex = 0;
            }

            // Write DllImport clauses
            if (bufferBuilder.Length != 0)
            {
                EnsureWhiteSpace(WriteTo.CS);
                Write(bufferBuilder.ToString(), WriteTo.CS);
            }

            WriteTabs(level, WriteTo.CS);
            WriteLine("}", WriteTo.CS);
            hasCSWhiteSpace = false;
            hasClassSeparatingWhitespace = false;
        }
Exemplo n.º 10
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($"{BulletParser.GetTypeRefName(method.ReturnType)} 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)
            {
                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($"{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($"({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;");
                }
            }
        }
Exemplo n.º 11
0
 public static string GetTypeMarshalConstructorStartCS(MethodDefinition method)
 {
     switch (method.ReturnType.Name)
     {
         case "btBroadphaseProxy":
             return "BroadphaseProxy.GetManaged(";
         case "btCollisionObject":
             return "CollisionObject.GetManaged(";
         case "btCollisionShape":
             return "CollisionShape.GetManaged(";
         case "btOverlappingPairCache":
             return "OverlappingPairCache.GetManaged(";
         case "IDebugDraw":
             return "DebugDraw.GetManaged(";
         case "btCollisionObjectWrapper":
             return $"new CollisionObjectWrapper(";
         default:
             return "";
     }
 }
Exemplo n.º 12
0
 public static string GetTypeMarshalConstructorEnd(MethodDefinition getter)
 {
     switch (getter.ReturnType.Name)
     {
         case "btCollisionShape":
         case "btIDebugDraw":
         case "btOverlappingPairCache":
         case "btQuaternion":
         case "btTransform":
         case "btVector4":
             return ")";
         default:
             return string.Empty;
     }
 }
Exemplo n.º 13
0
 public static string GetTypeMarshalConstructorStart(MethodDefinition getter)
 {
     switch (getter.ReturnType.Name)
     {
         case "btCollisionShape":
             return "CollisionShape::GetManaged(";
         case "btIDebugDraw":
             return "DebugDraw::GetManaged(";
         case "btOverlappingPairCache":
             return "OverlappingPairCache::GetManaged(";
         case "btQuaternion":
             return "Math::BtQuatToQuaternion(&";
         case "btTransform":
             return "Math::BtTransformToMatrix(&";
         case "btVector4":
             return "Math::BtVector4ToVector4(&";
         default:
             return string.Empty;
     }
 }
        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;
        }
        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;
        }
        private void CreateDestructors()
        {
            foreach (var @class in Project.ClassDefinitions.Values)
            {
                if (@class.BaseClass != null) continue;
                if (@class.NoInternalConstructor && @class.HidePublicConstructors) continue;
                if (@class.IsStatic) continue;
                if (@class is EnumDefinition) continue;
                if (@class.IsPureEnum) continue;

                var overloadIndex = @class.Methods.Count(m => m.Name.Equals("delete"));
                string name = overloadIndex == 0 ? "delete" : $"delete{overloadIndex + 1}";
                var deleteMethod = new MethodDefinition(name, @class, 0)
                {
                    IsDestructor = true,
                    ReturnType = new TypeRefDefinition("void")
                };
            }
        }
        // Create default constructor if no explicit C++ constructor exists.
        void CreateDefaultConstructors()
        {
            foreach (var @class in Project.ClassDefinitions.Values)
            {
                if (@class.HidePublicConstructors) continue;
                if (@class.IsStatic) continue;
                if (@class is EnumDefinition) continue;
                if (@class.IsPureEnum) continue;

                var constructors = @class.Methods.Where(m => m.IsConstructor);
                if (!constructors.Any())
                {
                    // Only possible if base class has a default constructor
                    if (@class.BaseClass == null || (@class.BaseClass != null &&
                        @class.BaseClass.Methods.Any(m => m.IsConstructor && !m.Parameters.Any())))
                    {
                        var constructor = new MethodDefinition(@class.Name, @class, 0)
                        {
                            IsConstructor = true,
                            ReturnType = new TypeRefDefinition("void")
                        };
                        //TODO:
                        //constructor.ManagedName = GetManagedMethodName(constructor);
                    }
                }
            }
        }
Exemplo n.º 18
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);
            }
        }
        private void WriteMethod(MethodDefinition method, int numOptionalParams = 0)
        {
            bool convertReturnType = _extensionClassesInternal.ContainsKey(method.ReturnType.ManagedName);

            bufferBuilder.Clear();
            WriteTabs(2, WriteTo.Buffer);
            Write("public unsafe static ", WriteTo.Buffer);
            if (convertReturnType)
            {
                Write(_extensionClassesExternal[method.ReturnType.ManagedName], WriteTo.Buffer);
            }
            else
            {
                Write(method.ReturnType.ManagedName, WriteTo.Buffer);
            }
            Write(string.Format(" {0}(this {1} obj",
                method.ManagedName, method.Parent.ManagedName), WriteTo.Buffer);

            var extendedParams = new List<ParameterDefinition>();
            int numParameters = method.Parameters.Length - numOptionalParams;
            for (int i = 0; i < numParameters; i++)
            {
                Write(", ", WriteTo.Buffer);

                var param = method.Parameters[i];
                if (_extensionClassesInternal.ContainsKey(param.Type.ManagedName))
                {
                    Write(string.Format("ref {0} {1}",
                        _extensionClassesExternal[param.Type.ManagedName], param.Name), WriteTo.Buffer);
                    extendedParams.Add(param);
                }
                else
                {
                    Write(string.Format("{0} {1}", param.Type.ManagedName, param.Name), WriteTo.Buffer);
                }
            }
            WriteLine(')', WriteTo.Buffer);

            WriteTabs(2, WriteTo.Buffer);
            WriteLine('{', WriteTo.Buffer);

            // Fix parameter pointers
            int tabs = 3;
            foreach (var param in extendedParams)
            {
                WriteTabs(tabs, WriteTo.Buffer);
                WriteLine(string.Format("fixed ({0}* {1}Ptr = &{2})",
                    _extensionClassesExternal[param.Type.ManagedName], param.Name, param.Name), WriteTo.Buffer);
                WriteTabs(tabs, WriteTo.Buffer);
                WriteLine('{', WriteTo.Buffer);
                tabs++;
            }

            WriteTabs(tabs, WriteTo.Buffer);
            if (method.ReturnType.Name != "void")
            {
                Write("return ", WriteTo.Buffer);
            }
            Write(string.Format("obj.{0}(", method.ManagedName), WriteTo.Buffer);
            bool hasOptionalParam = false;
            for (int i = 0; i < numParameters; i++)
            {
                var param = method.Parameters[i];
                if (_extensionClassesInternal.ContainsKey(param.Type.ManagedName))
                {
                    Write(string.Format("ref *({0}*){1}Ptr",
                        _extensionClassesInternal[param.Type.ManagedName], param.Name), WriteTo.Buffer);
                }
                else
                {
                    Write(param.Name, WriteTo.Buffer);
                }

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

                if (i != numParameters - 1)
                {
                    Write(", ", WriteTo.Buffer);
                }
            }
            Write(')', WriteTo.Buffer);
            if (convertReturnType)
            {
                Write(_returnTypeConversion[method.ReturnType.ManagedName], WriteTo.Buffer);
            }
            WriteLine(';', WriteTo.Buffer);

            // Close fixed blocks
            while (tabs != 2)
            {
                tabs--;
                WriteTabs(tabs, WriteTo.Buffer);
                WriteLine('}', WriteTo.Buffer);
            }

            _extensionMethods.Add(new KeyValuePair<string, string>(method.Name, bufferBuilder.ToString()));

            if (hasOptionalParam)
            {
                WriteMethod(method, numOptionalParams + 1);
            }
        }
Exemplo n.º 20
0
 public static string GetTypeMarshalConstructorEndCS(MethodDefinition method)
 {
     if (GetTypeMarshalConstructorStartCS(method) != "")
     {
         return ")";
     }
     return "";
 }
Exemplo n.º 21
0
        void OutputMethodMarshal(MethodDefinition method, int numParameters)
        {
            if (method.IsConstructor)
            {
                SourceWrite(method.Parent.FullyQualifiedName);
            }
            else
            {
                SourceWrite(method.Name);
            }
            SourceWrite('(');
            for (int i = 0; i < numParameters; i++)
            {
                var param = method.Parameters[i];
                string marshal = BulletParser.GetTypeMarshalCppCli(param);
                if (!string.IsNullOrEmpty(marshal))
                {
                    SourceWrite(marshal);
                }
                else if (param.Type.IsBasic)
                {
                    SourceWrite(param.ManagedName);
                }
                else
                {
                    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.IsPointer && param.Type.ManagedName.Equals("void"))
                    {
                        SourceWrite(".ToPointer()");
                    }
                    else
                    {
                        SourceWrite("->_native");
                    }
                }

                // Insert comma if there are more parameters
                if (i != numParameters - 1)
                {
                    if (_sourceLineLength >= LineBreakWidth)
                    {
                        SourceWriteLine(",");
                        WriteTabs(2, true);
                    }
                    else
                    {
                        SourceWrite(", ");
                    }
                }
            }
            SourceWrite(')');
        }
        private void WriteMethodDeclaration(MethodDefinition method, int numParameters, int level, int overloadIndex,
            MethodDefinition returnParamMethod = null)
        {
            // Do not write accessor methods of C# properties
            WriteTo cs = (method.Property == null) ? WriteTo.CS : WriteTo.None;

            // Cached properties that are initialized only once do not need a DllImport for the get method
            WriteTo dllImport;
            if (method.Property != null && method.Property.Setter == null &&
                method.Parent.CachedProperties.ContainsKey(method.Property.Name))
            {
                dllImport = WriteTo.None;
            }
            else
            {
                dllImport = WriteTo.Buffer;
            }

            // Skip delete methods in classes that can't be constructed (including all subclasses).
            if (method.Name.Equals("delete"))
            {
                if (method.Parent.HidePublicConstructors)
                {
                    // TODO: Check all subclasses
                    //return;
                }
            }

            WriteTabs(1);
            Write("EXPORT ", WriteTo.Header);

            WriteTabs(level + 1, cs);
            Write("public ", cs);

            // DllImport clause
            WriteTabs(level + 1, dllImport);
            WriteLine("[DllImport(Native.Dll, CallingConvention = Native.Conv), SuppressUnmanagedCodeSecurity]", dllImport);
            if (method.ReturnType != null && method.ReturnType.ManagedName.Equals("bool"))
            {
                WriteTabs(level + 1, dllImport);
                WriteLine("[return: MarshalAs(UnmanagedType.I1)]", dllImport);
            }
            WriteTabs(level + 1, dllImport);
            Write("static extern ", dllImport);

            // Return type
            if (method.IsConstructor)
            {
                Write(method.Parent.FullNameC, WriteTo.Header);
                Write(method.Parent.FullyQualifiedName, WriteTo.Source);
                Write("* ", WriteTo.Header | WriteTo.Source);
                Write("IntPtr ", dllImport);
            }
            else
            {
                if (method.IsStatic)
                {
                    Write("static ", cs);
                }
                WriteType(method.ReturnType, WriteTo.Header | WriteTo.Source);
                if (cs != 0)
                {
                    WriteTypeCS((returnParamMethod != null) ? returnParamMethod.ReturnType : method.ReturnType);
                }
                Write(' ', WriteTo.Header | WriteTo.Source | cs);
                if (method.ReturnType.IsBasic)
                {
                    Write(method.ReturnType.ManagedNameCS, dllImport);
                }
                else if (method.ReturnType.HasTemplateTypeParameter)
                {
                    Write(method.ReturnType.ManagedNameCS, dllImport);
                }
                else if (method.ReturnType.Referenced != null)
                {
                    Write("IntPtr", dllImport);
                }
                else
                {
                    // Return structures to an additional out parameter, not immediately
                    Write("void", dllImport);
                }
                Write(' ', dllImport);
            }

            // Name
            string methodName = method.IsConstructor ? "new" : method.Name;
            Write($"{method.Parent.FullNameC}_{methodName}",
                WriteTo.Header | WriteTo.Source | dllImport);

            if (methodName.Equals("delete"))
            {
                WriteDeleteMethodCS(method, level);
            }
            else
            {
                string methodNameManaged = method.IsConstructor ? method.Parent.ManagedName : method.ManagedName;
                Write(methodNameManaged, cs);
            }

            // Index number for overloaded methods
            if (overloadIndex != 0)
            {
                Write((overloadIndex + 1).ToString(), WriteTo.Header | WriteTo.Source | dllImport);
            }


            // Parameters
            if (!method.Name.Equals("delete"))
            {
                Write('(', cs);
            }
            Write('(', WriteTo.Header | WriteTo.Source | dllImport);

            // The first parameter is the instance pointer (if not constructor or static method)
            if (!method.IsConstructor && !method.IsStatic)
            {
                Write($"{method.Parent.FullNameC}* obj", WriteTo.Header);
                Write($"{method.Parent.FullyQualifiedName}* obj", WriteTo.Source);
                Write("IntPtr obj", dllImport);

                if (numParameters != 0)
                {
                    Write(", ", WriteTo.Header | WriteTo.Source | dllImport);
                }
            }

            for (int i = 0; i < numParameters; i++)
            {
                bool isFinalParameter = (i == numParameters - 1);
                bool isCsFinalParameter = returnParamMethod != null && isFinalParameter;
                var param = method.Parameters[i];

                // Parameter type
                if (!isCsFinalParameter)
                {
                    if (param.Type.Referenced != null && !(param.Type.IsConst || param.Type.Referenced.IsConst) &&
                        BulletParser.MarshalStructByValue(param.Type))
                    {
                        Write("out ", cs);
                    }
                }
                WriteType(param.Type, WriteTo.Header | WriteTo.Source);
                if (cs != 0 && !isCsFinalParameter)
                {
                    WriteTypeCS(param.Type);
                }
                Write(BulletParser.GetTypeDllImport(param.Type), dllImport);

                // Parameter name
                if (!isCsFinalParameter)
                {
                    Write($" {param.ManagedName}", cs);
                }
                Write($" {param.Name}", WriteTo.Header | WriteTo.Source | dllImport);

                if (!isFinalParameter)
                {
                    Write(", ", WriteTo.Header | WriteTo.Source | dllImport);
                }
                if (!(isFinalParameter || (returnParamMethod != null && i == numParameters - 2)))
                {
                    Write(", ", WriteTo.CS);
                }
            }
            WriteLine(");", WriteTo.Header | dllImport);
            if (!method.Name.Equals("delete"))
            {
                WriteLine(')', cs);
            }
            WriteLine(')', WriteTo.Source);
        }
Exemplo n.º 23
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($"#ifndef {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 = $"{method.Property.Name}::{headerMethodName}";
            }
            else
            {
                headerMethodName = method.ManagedName;
                sourceMethodName = headerMethodName;
            }
            HeaderWrite($"{headerMethodName}(");
            SourceWrite($"{parentClass.FullNameCppCli}::{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($"{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($": {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 = $"\t{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);
            }
        }
        void WriteClass(ClassDefinition c, int level)
        {
            if (c.IsExcluded || c.IsTypedef || c.IsPureEnum ||
                c is ClassTemplateDefinition || c is EnumDefinition)
            {
                return;
            }

            if (wrapperHeaderGuards.ContainsKey(c.Name))
            {
                WriteClassWrapper(c);
            }

            // Write class definition
            EnsureWhiteSpace(WriteTo.CS);
            WriteTabs(level, WriteTo.CS);
            Write("public ", WriteTo.CS);
            if (c.IsAbstract)
            {
                Write("abstract ", WriteTo.CS);
            }
            Write($"class {c.ManagedName}", WriteTo.CS);
            if (c.BaseClass != null)
            {
                Write(" : ", WriteTo.CS);
                WriteLine(c.BaseClass.FullNameCppCli.Replace("::", "."), WriteTo.CS);
            }
            else if (c.IsStaticClass)
            {
                WriteLine(WriteTo.CS);
            }
            else
            {
                WriteLine(" : IDisposable", WriteTo.CS);
            }
            WriteTabs(level, WriteTo.CS);
            WriteLine("{", WriteTo.CS);
            hasCSWhiteSpace = true;

            // Write child classes
            foreach (var cl in c.Classes.OrderBy(x => x.FullNameCppCli))
            {
                WriteClass(cl, level + 1);
            }

            // Write the native pointer to the base class
            if (c.BaseClass == null && !c.IsStaticClass)
            {
                EnsureWhiteSpace(WriteTo.CS);
                WriteTabs(level + 1, WriteTo.CS);
                WriteLine("internal IntPtr _native;", WriteTo.CS);
                if (c.HasPreventDelete)
                {
                    WriteTabs(level + 1, WriteTo.CS);
                    WriteLine("bool _preventDelete;", WriteTo.CS);
                    hasCSWhiteSpace = false;
                }
                hasCSWhiteSpace = false;
            }

            // Write cached property fields
            if (c.CachedProperties.Any())
            {
                EnsureWhiteSpace(WriteTo.CS);
                foreach (var cachedProperty in c.CachedProperties.OrderBy(p => p.Key))
                {
                    WriteTabs(level + 1, WriteTo.CS);
                    string name = cachedProperty.Key;
                    name = char.ToLower(name[0]) + name.Substring(1);
                    WriteLine(string.Format("{0} {1} _{2};",
                        cachedProperty.Value.Access.ToString().ToLower(),
                        cachedProperty.Value.Property.Type.ManagedNameCS,
                        name), WriteTo.CS);
                }
                hasCSWhiteSpace = false;
            }

            // Write methods
            bufferBuilder.Clear();

            // Write constructors
            if (!c.IsStaticClass)
            {
                // Write C# internal constructor
                if (!c.NoInternalConstructor)
                {
                    EnsureWhiteSpace(WriteTo.CS);
                    WriteTabs(level + 1, WriteTo.CS);
                    Write($"internal {c.ManagedName}(IntPtr native", WriteTo.CS);
                    if (c.HasPreventDelete)
                    {
                        Write(", bool preventDelete", WriteTo.CS);
                    }
                    WriteLine(')', WriteTo.CS);
                    if (c.BaseClass != null)
                    {
                        WriteTabs(level + 2, WriteTo.CS);
                        Write(": base(native", WriteTo.CS);
                        if (c.HasPreventDelete)
                        {
                            if (!c.BaseClass.HasPreventDelete)
                            {
                                // Base class should also have preventDelete
                                //throw new NotImplementedException();
                            }
                            Write(", preventDelete", WriteTo.CS);
                        }
                        else
                        {
                            if (c.BaseClass.HasPreventDelete)
                            {
                                Write(", true", WriteTo.CS);
                            }
                        }
                        WriteLine(')', WriteTo.CS);
                    }
                    WriteTabs(level + 1, WriteTo.CS);
                    WriteLine('{', WriteTo.CS);
                    if (c.BaseClass == null)
                    {
                        WriteTabs(level + 2, WriteTo.CS);
                        WriteLine("_native = native;", WriteTo.CS);
                        if (c.HasPreventDelete)
                        {
                            WriteTabs(level + 2, WriteTo.CS);
                            WriteLine("_preventDelete = preventDelete;", WriteTo.CS);
                        }
                    }
                    WriteTabs(level + 1, WriteTo.CS);
                    WriteLine('}', WriteTo.CS);
                    hasCSWhiteSpace = false;
                }

                // Write public constructors
                if (!c.HidePublicConstructors && !c.IsAbstract)
                {
                    int overloadIndex = 0;
                    var constructors = c.Methods.Where(m => m.IsConstructor && !m.IsExcluded);
                    if (constructors.Any())
                    {
                        foreach (var constructor in constructors)
                        {
                            WriteMethod(constructor, level, ref overloadIndex);
                        }
                    }
                }
            }

            // Write methods
            var methods = c.Methods.Where(m => !m.IsConstructor && !m.IsExcluded).OrderBy(m => m.Name);
            var methodsOverloads = methods.GroupBy(m => m.Name);
            foreach (var groupByName in methodsOverloads)
            {
                int overloadIndex = 0;
                foreach (var method in groupByName)
                {
                    WriteMethod(method, level, ref overloadIndex);
                }
            }

            // Write properties
            foreach (var prop in c.Properties)
            {
                WriteProperty(prop, level);
            }

            // Write delete method
            if (c.BaseClass == null && !c.IsStaticClass)
            {
                int overloadIndex = 0;
                var del = new MethodDefinition("delete", c, 0);
                del.ReturnType = new TypeRefDefinition();
                WriteMethod(del, level, ref overloadIndex);
                c.Methods.Remove(del);
            }

            // Write DllImport clauses
            if (bufferBuilder.Length != 0)
            {
                EnsureWhiteSpace(WriteTo.CS);
                Write(bufferBuilder.ToString(), WriteTo.CS);
            }

            WriteTabs(level, WriteTo.CS);
            WriteLine("}", WriteTo.CS);
            hasCSWhiteSpace = false;
            hasCppClassSeparatingWhitespace = false;
        }
Exemplo n.º 25
0
        void WriteMethodDefinition(MethodDefinition method, int numParameters, int overloadIndex, int level, MethodDefinition returnParamMethod)
        {
            // Skip methods wrapped by C# properties
            WriteTo cs = (method.Property == null) ? WriteTo.CS : WriteTo.None;

            // Field marshalling
            if (method.Field != null && method.Field.Type.Referenced == null && BulletParser.MarshalStructByValue(method.Field.Type))
            {
                WriteTabs(1, WriteTo.Source);
                if (method.Property.Getter.Name == method.Name)
                {
                    WriteLine(BulletParser.GetFieldGetterMarshal(method.Parameters[0], method.Field), WriteTo.Source);
                }
                else
                {
                    WriteLine(BulletParser.GetFieldSetterMarshal(method.Parameters[0], method.Field), WriteTo.Source);
                }
                return;
            }

            int numParametersOriginal = numParameters;
            if (returnParamMethod != null)
            {
                numParametersOriginal--;
            }

            bool needTypeMarshalEpilogue = false;
            if (!(method.Property != null && BulletParser.MarshalStructByValue(method.Property.Type) && method.Property.Getter.Name == method.Name))
            {
                // Type marshalling prologue
                for (int i = 0; i < numParametersOriginal; i++)
                {
                    var param = method.Parameters[i];
                    string prologue = BulletParser.GetTypeMarshalPrologue(param, method);
                    if (!string.IsNullOrEmpty(prologue))
                    {
                        WriteTabs(1, WriteTo.Source);
                        WriteLine(prologue, WriteTo.Source);
                    }

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

            WriteTabs(1, WriteTo.Source);

            if (returnParamMethod != null)
            {
                // Temporary variable
                Write(BulletParser.GetTypeNameCS(returnParamMethod.ReturnType), cs);
                Write(' ', cs);
                Write(method.Parameters[numParametersOriginal].ManagedName, cs);
                WriteLine(';', cs);
                WriteTabs(level + 2, cs);

                Write(BulletParser.GetReturnValueMarshalStart(returnParamMethod.ReturnType), WriteTo.Source);
            }

            if (method.IsConstructor)
            {
                Write("return new ", WriteTo.Source);
                Write(method.Parent.FullName, WriteTo.Source);
                if (method.Parent.BaseClass == null)
                {
                    Write("_native = ", WriteTo.CS);
                }
                Write(method.Parent.FullNameCS, WriteTo.CS);
                Write("_new", WriteTo.CS);
            }
            else
            {
                if (!method.IsVoid)
                {
                    var returnType = method.ReturnType;
                    if (needTypeMarshalEpilogue)
                    {
                        // Store return value in a temporary variable
                        Write(BulletParser.GetTypeRefName(returnType), WriteTo.Source);
                        Write(" ret = ", WriteTo.Source);
                    }
                    else
                    {
                        // Return immediately
                        Write("return ", WriteTo.Source);
                    }

                    Write("return ", cs);
                    Write(BulletParser.GetTypeMarshalConstructorStartCS(method), cs);

                    if (!returnType.IsBasic && !returnType.IsPointer && !returnType.IsConstantArray)
                    {
                        if (!(returnType.Target != null && returnType.Target.IsPureEnum))
                        {
                            Write('&', WriteTo.Source);
                        }

                    }
                }

                if (method.IsStatic)
                {
                    Write(method.Parent.Name, WriteTo.Source);
                    Write("::", WriteTo.Source);
                }
                else
                {
                    Write("obj->", WriteTo.Source);
                }
                if (method.Field == null)
                {
                    Write(method.Name, WriteTo.Source);
                }

                Write(method.Parent.FullNameCS, cs);
                Write('_', cs);
                Write(method.Name, cs);
            }
            if (overloadIndex != 0)
            {
                Write((overloadIndex + 1).ToString(), cs);
            }

            // Call parameters
            if (method.Field != null)
            {
                Write(method.Field.Name, WriteTo.Source);
                if (method.Property.Setter != null && method.Name.Equals(method.Property.Setter.Name))
                {
                    Write(" = value", WriteTo.Source);
                }
                WriteLine(';', WriteTo.Source);
            }
            else
            {
                Write('(', WriteTo.Source);

                for (int i = 0; i < numParametersOriginal; i++)
                {
                    var param = method.Parameters[i];

                    string marshal = BulletParser.GetTypeMarshal(param);
                    if (!string.IsNullOrEmpty(marshal))
                    {
                        Write(marshal, WriteTo.Source);
                    }
                    else
                    {
                        if (!param.Type.IsBasic && !param.Type.IsPointer && !param.Type.IsConstantArray)
                        {
                            Write('*', WriteTo.Source);
                        }
                        Write(param.Name, WriteTo.Source);
                    }

                    if (i != numParametersOriginal - 1)
                    {
                        Write(", ", WriteTo.Source);
                    }
                }

                if (returnParamMethod != null)
                {
                    WriteLine(BulletParser.GetReturnValueMarshalEnd(method.Parameters[numParametersOriginal]), WriteTo.Source);
                }
                else
                {
                    WriteLine(");", WriteTo.Source);
                }
            }

            if (cs != 0)
            {
                Write('(', WriteTo.CS);
                if (!method.IsConstructor && !method.IsStatic)
                {
                    Write("_native", WriteTo.CS);
                    if (numParametersOriginal != 0)
                    {
                        Write(", ", WriteTo.CS);
                    }
                }

                for (int i = 0; i < numParameters; i++)
                {
                    var param = method.Parameters[i];
                    Write(BulletParser.GetTypeCSMarshal(param), WriteTo.CS);

                    if (i != numParameters - 1)
                    {
                        Write(", ", WriteTo.CS);
                    }
                }

                if (method.IsConstructor && method.Parent.BaseClass != null)
                {
                    Write(")", WriteTo.CS);
                    if (method.Parent.BaseClass.Target.HasPreventDelete)
                    {
                        Write(", false");
                    }
                    WriteLine(")", WriteTo.CS);
                    WriteTabs(level + 1, WriteTo.CS);
                    WriteLine('{', WriteTo.CS);
                }
                else
                {
                    if (!method.IsConstructor && !method.IsVoid)
                    {
                        Write(BulletParser.GetTypeMarshalConstructorEndCS(method), cs);
                    }
                    WriteLine(");", WriteTo.CS);
                }
            }

            // Return temporary variable
            if (returnParamMethod != null)
            {
                WriteTabs(level + 2, cs);
                Write("return ", cs);
                Write(method.Parameters[numParametersOriginal].ManagedName, cs);
                WriteLine(';', cs);
            }

            // Write type marshalling epilogue
            if (needTypeMarshalEpilogue)
            {
                for (int i = 0; i < numParametersOriginal; i++)
                {
                    var param = method.Parameters[i];
                    string epilogue = BulletParser.GetTypeMarshalEpilogue(param);
                    if (!string.IsNullOrEmpty(epilogue))
                    {
                        WriteTabs(1, WriteTo.Source);
                        WriteLine(epilogue, WriteTo.Source);
                    }
                }

                if (!method.IsVoid)
                {
                    WriteTabs(1, WriteTo.Source);
                    WriteLine("return ret;", WriteTo.Source);
                }
            }
        }
Exemplo n.º 26
0
        void WriteMethod(MethodDefinition method, int level, ref int overloadIndex, int numOptionalParams = 0)
        {
            EnsureWhiteSpace(WriteTo.Source);
            if (!_hasCppClassSeparatingWhitespace)
            {
                WriteLine(WriteTo.Header | WriteTo.Source);
                _hasCppClassSeparatingWhitespace = true;
            }

            EnsureWhiteSpace(WriteTo.Source);

            int numOptionalParamsTotal = method.NumOptionalParameters;
            int numParameters = method.Parameters.Length - numOptionalParamsTotal + numOptionalParams;

            WriteMethodDeclaration(method, numParameters, level, overloadIndex);

            // Method body
            WriteLine('{', WriteTo.Source);
            WriteMethodDefinition(method, numParameters, level, overloadIndex);
            WriteLine('}', WriteTo.Source);
            hasSourceWhiteSpace = false;

            // If there are optional parameters, then output all possible combinations of calls
            overloadIndex++;
            if (numOptionalParams < numOptionalParamsTotal)
            {
                WriteMethod(method, level, ref overloadIndex, numOptionalParams + 1);
            }
        }
Exemplo n.º 27
0
        void WriteDeleteMethod(MethodDefinition method, int level)
        {
            // public void Dispose()
            WriteLine("Dispose()", WriteTo.CS);
            WriteTabs(level + 1, WriteTo.CS);
            WriteLine('{', WriteTo.CS);
            WriteTabs(level + 2, WriteTo.CS);
            WriteLine("Dispose(true);", WriteTo.CS);
            WriteTabs(level + 2, WriteTo.CS);
            WriteLine("GC.SuppressFinalize(this);", WriteTo.CS);
            WriteTabs(level + 1, WriteTo.CS);
            WriteLine('}', WriteTo.CS);

            // protected virtual void Dispose(bool disposing)
            WriteLine(WriteTo.CS);
            WriteTabs(level + 1, WriteTo.CS);
            WriteLine("protected virtual void Dispose(bool disposing)", WriteTo.CS);
            WriteTabs(level + 1, WriteTo.CS);
            WriteLine("{", WriteTo.CS);
            WriteTabs(level + 2, WriteTo.CS);
            WriteLine("if (_native != IntPtr.Zero)", WriteTo.CS);
            WriteTabs(level + 2, WriteTo.CS);
            WriteLine('{', WriteTo.CS);
            if (method.Parent.HasPreventDelete)
            {
                WriteTabs(level + 3, WriteTo.CS);
                WriteLine("if (!_preventDelete)", WriteTo.CS);
                WriteTabs(level + 3, WriteTo.CS);
                WriteLine('{', WriteTo.CS);
                WriteTabs(level + 4, WriteTo.CS);
                Write(method.Parent.FullNameCS, WriteTo.CS);
                WriteLine("_delete(_native);", WriteTo.CS);
                WriteTabs(level + 3, WriteTo.CS);
                WriteLine('}', WriteTo.CS);
            }
            else
            {
                WriteTabs(level + 3, WriteTo.CS);
                Write(method.Parent.FullNameCS, WriteTo.CS);
                WriteLine("_delete(_native);", WriteTo.CS);
            }
            WriteTabs(level + 3, WriteTo.CS);
            WriteLine("_native = IntPtr.Zero;", WriteTo.CS);
            WriteTabs(level + 2, WriteTo.CS);
            WriteLine('}', WriteTo.CS);
            WriteTabs(level + 1, WriteTo.CS);
            WriteLine('}', WriteTo.CS);

            // C# Destructor
            WriteLine(WriteTo.CS);
            WriteTabs(level + 1, WriteTo.CS);
            Write('~', WriteTo.CS);
            Write(method.Parent.ManagedName, WriteTo.CS);
            WriteLine("()", WriteTo.CS);
            WriteTabs(level + 1, WriteTo.CS);
            WriteLine('{', WriteTo.CS);
            WriteTabs(level + 2, WriteTo.CS);
            WriteLine("Dispose(false);", WriteTo.CS);
            WriteTabs(level + 1, WriteTo.CS);
            WriteLine('}', WriteTo.CS);
        }
Exemplo n.º 28
0
        void WriteMethodDefinition(MethodDefinition method, int numParameters, int level, int overloadIndex)
        {
            To = WriteTo.Source;

            if (method.IsDestructor)
            {
                WriteLine(1, "delete obj;", WriteTo.Source);
                return;
            }

            string qualifier = method.IsStatic ? $"{method.Parent.Name}::" : "obj->";

            // Struct field marshalling
            var field = method.Field;
            if (field != null)
            {
                string fieldName = $"{qualifier}{field.Name}";
                if (field.Type.Target != null && field.Type.Target.MarshalAsStruct)
                {
                    string macroPrefix = field.Type.Name.ToUpper();
                    string paramName = (method.OutValueParameter != null ? method.OutValueParameter : method.Parameters[0]).Name;
                    if (method == field.Getter)
                    {
                        WriteLine(1, $"{macroPrefix}_SET({paramName}, {fieldName});");
                    }
                    else
                    {
                        WriteLine(1, $"{macroPrefix}_COPY(&{fieldName}, {paramName});");
                    }
                }
                else if (method == field.Getter)
                {
                    if (field.Type.Kind == TypeKind.Record)
                    {
                        WriteLine(1, $"return &{qualifier}{field.Name};");
                    }
                    else
                    {
                        WriteLine(1, $"return {qualifier}{field.Name};");
                    }
                }
                else
                {
                    WriteLine(1, $"{qualifier}{field.Name} = value;");
                }
                return;
            }

            // Parameter marshalling prologues
            bool needTypeMarshalEpilogue = false;
            foreach (var param in method.Parameters.Take(numParameters))
            {
                if (param.Type.Kind == TypeKind.LValueReference &&
                    param.Type.Referenced.Target != null &&
                    param.Type.Referenced.Target.MarshalAsStruct)
                {
                    string macroPrefix = param.Type.Referenced.Target.Name.ToUpper();
                    if (param.MarshalDirection == MarshalDirection.Out)
                    {
                        WriteLine(1, $"{macroPrefix}_DEF({param.Name});");
                        needTypeMarshalEpilogue = true;
                    }
                    else
                    {
                        WriteLine(1, $"{macroPrefix}_IN({param.Name});");
                        if (param.MarshalDirection == MarshalDirection.InOut)
                        {
                            needTypeMarshalEpilogue = true;
                        }
                    }
                }
            }

            WriteTabs(1);

            if (method.IsConstructor)
            {
                Write($"return new {method.Parent.FullyQualifiedName}");
            }
            else
            {
                if (!method.IsVoid)
                {
                    var returnType = method.ReturnType.Canonical;

                    if (method.OutValueParameter != null)
                    {
                        string macroPrefix = method.OutValueParameter.Type.Referenced.Name.ToUpper();
                        if (returnType.Kind == TypeKind.LValueReference)
                        {
                            Write($"{macroPrefix}_COPY({method.OutValueParameter.Name}, &");
                        }
                        else
                        {
                            Write($"{macroPrefix}_SET({method.OutValueParameter.Name}, ");
                        }
                    }
                    else
                    {
                        if (needTypeMarshalEpilogue)
                        {
                            // Save the return value and return it after the epilogues
                            Write($"{GetTypeNameC(method.ReturnType)} ret = ");
                        }
                        else
                        {
                            // Return immediately
                            Write("return ");
                        }

                        switch (returnType.Kind)
                        {
                            case TypeKind.LValueReference:
                            case TypeKind.Record:
                                if (!(returnType.Target != null && returnType.Target is EnumDefinition))
                                {
                                    Write('&');
                                }
                                break;
                        }
                    }
                }

                Write($"{qualifier}{method.Name}");
            }

            // Call parameters
            var originalParams = method.Parameters.Take(numParameters)
                .Select(p =>
                {
                    if (p.Type.Target != null && p.Type.Target.MarshalAsStruct)
                    {
                        string macroPrefix = p.Type.Target.Name.ToUpper();
                        return $"{macroPrefix}_USE({p.Name})";
                    }

                    if (p.Type.Kind == TypeKind.LValueReference && p.Type.Referenced.Target != null && p.Type.Referenced.Target.MarshalAsStruct)
                    {
                        string macroPrefix = p.Type.Referenced.Target.Name.ToUpper();
                        return $"{macroPrefix}_USE({p.Name})";
                    }

                    var type = p.Type.Canonical;
                    if (type.Kind == TypeKind.LValueReference)
                    {
                        return $"*{p.Name}";
                    }
                    return p.Name;
                });
            Write("(");
            Write($"{ListToLines(originalParams, WriteTo.Source, 1)})");
            if (method.OutValueParameter != null)
            {
                Write(")");
            }
            WriteLine(";");

            // Write type marshalling epilogue
            if (needTypeMarshalEpilogue)
            {
                foreach (var param in method.Parameters.Take(numParameters)
                    .Where(p => p.MarshalDirection == MarshalDirection.Out ||
                        p.MarshalDirection == MarshalDirection.InOut))
                {
                    if (param.Type.Kind == TypeKind.LValueReference &&
                        param.Type.Referenced.Target != null &&
                        param.Type.Referenced.Target.MarshalAsStruct)
                    {
                        string macroPrefix = param.Type.Referenced.Target.Name.ToUpper();
                        WriteLine(1, $"{macroPrefix}_DEF_OUT({param.Name});");
                    }
                }

                if (!method.IsVoid)
                {
                    WriteLine(1, "return ret;");
                }
            }
        }
Exemplo n.º 29
0
        void WriteMethodDeclaration(MethodDefinition method, int numParameters, int level, int overloadIndex, MethodDefinition returnParamMethod = null)
        {
            // Skip methods wrapped by C# properties
            WriteTo cs = (method.Property == null) ? WriteTo.CS : WriteTo.None;

            WriteTabs(1);
            Write("EXPORT ", WriteTo.Header);

            WriteTabs(level + 1, cs);
            Write("public ", cs);

            // DllImport clause
            WriteTabs(level + 1, WriteTo.Buffer);
            WriteLine("[DllImport(Native.Dll, CallingConvention = Native.Conv), SuppressUnmanagedCodeSecurity]", WriteTo.Buffer);
            if (method.ReturnType != null && method.ReturnType.ManagedName.Equals("bool"))
            {
                WriteTabs(level + 1, WriteTo.Buffer);
                WriteLine("[return: MarshalAs(UnmanagedType.I1)]", WriteTo.Buffer);
            }
            WriteTabs(level + 1, WriteTo.Buffer);
            Write("static extern ", WriteTo.Buffer);

            // Return type
            if (method.IsConstructor)
            {
                Write(method.Parent.FullNameCS, WriteTo.Header);
                Write(method.Parent.FullName, WriteTo.Source);
                Write("* ", WriteTo.Header | WriteTo.Source);
                Write("IntPtr ", WriteTo.Buffer);
            }
            else
            {
                if (method.IsStatic)
                {
                    Write("static ", cs);
                }
                WriteType(method.ReturnType, WriteTo.Header | WriteTo.Source);
                if (cs != 0)
                {
                    WriteTypeCS((returnParamMethod != null) ? returnParamMethod.ReturnType : method.ReturnType);
                }
                Write(' ', WriteTo.Header | WriteTo.Source | cs);
                if (method.ReturnType.IsBasic)
                {
                    Write(method.ReturnType.ManagedNameCS, WriteTo.Buffer);
                }
                else if (method.ReturnType.HasTemplateTypeParameter)
                {
                    Write(method.ReturnType.ManagedNameCS, WriteTo.Buffer);
                }
                else if (method.ReturnType.Referenced != null)
                {
                    Write("IntPtr", WriteTo.Buffer);
                }
                else
                {
                    // Return structures to an additional out parameter, not immediately
                    Write("void", WriteTo.Buffer);
                }
                Write(' ', WriteTo.Buffer);
            }

            // Name
            Write(method.Parent.FullNameCS, WriteTo.Header | WriteTo.Source | WriteTo.Buffer);
            Write('_', WriteTo.Header | WriteTo.Source | WriteTo.Buffer);
            if (method.IsConstructor)
            {
                Write("new", WriteTo.Header | WriteTo.Source | WriteTo.Buffer);
                Write(method.Parent.ManagedName, WriteTo.CS);
            }
            else
            {
                Write(method.Name, WriteTo.Header | WriteTo.Source | WriteTo.Buffer);
                if (method.Name.Equals("delete"))
                {
                    WriteDeleteMethod(method, level);
                }
                else
                {
                    Write(method.ManagedName, cs);
                }
            }

            // Index number for overloaded methods
            if (overloadIndex != 0)
            {
                Write((overloadIndex + 1).ToString(), WriteTo.Header | WriteTo.Source | WriteTo.Buffer);
            }

            // Parameters
            if (!method.Name.Equals("delete"))
            {
                Write('(', cs);
            }
            Write('(', WriteTo.Header | WriteTo.Source | WriteTo.Buffer);

            // The first parameter is the instance pointer (if not constructor or static method)
            if (!method.IsConstructor && !method.IsStatic)
            {
                Write(method.Parent.FullNameCS, WriteTo.Header);
                Write(method.Parent.FullName, WriteTo.Source);
                Write("* obj", WriteTo.Header | WriteTo.Source);
                Write("IntPtr obj", WriteTo.Buffer);

                if (numParameters != 0)
                {
                    Write(", ", WriteTo.Header | WriteTo.Source | WriteTo.Buffer);
                }
            }

            for (int i = 0; i < numParameters; i++)
            {
                bool isFinalParameter = (i == numParameters - 1);
                bool isCsFinalParameter = (returnParamMethod != null) ? isFinalParameter : false;
                var param = method.Parameters[i];

                // Parameter type
                if (!isCsFinalParameter)
                {
                    if (param.Type.Referenced != null && !(param.Type.IsConst || param.Type.Referenced.IsConst) &&
                        BulletParser.MarshalStructByValue(param.Type))
                    {
                        Write("out ", cs);
                    }
                }
                WriteType(param.Type, WriteTo.Header | WriteTo.Source);
                if (cs != 0 && !isCsFinalParameter)
                {
                    WriteTypeCS(param.Type);
                }
                Write(BulletParser.GetTypeDllImport(param.Type), WriteTo.Buffer);

                // Parameter name
                if (!isCsFinalParameter)
                {
                    Write(' ', cs);
                    Write(param.ManagedName, cs);
                }
                Write(' ', WriteTo.Header | WriteTo.Source | WriteTo.Buffer);
                Write(param.Name, WriteTo.Header | WriteTo.Source | WriteTo.Buffer);

                if (!isFinalParameter)
                {
                    Write(", ", WriteTo.Header | WriteTo.Source | WriteTo.Buffer);
                }
                if (!(isFinalParameter || (returnParamMethod != null && i == numParameters - 2)))
                {
                    Write(", ", WriteTo.CS);
                }
            }
            WriteLine(");", WriteTo.Header | WriteTo.Buffer);
            if (!method.Name.Equals("delete"))
            {
                WriteLine(')', cs);
            }
            WriteLine(')', WriteTo.Source);
        }
Exemplo n.º 30
0
        public static string GetTypeMarshalPrologue(ParameterDefinition parameter, MethodDefinition method)
        {
            if (method.Field != null)
            {
                return null;
            }

            switch (parameter.Type.ManagedName)
            {
                case "Quaternion":
                    return "QUATERNION_CONV(" + parameter.Name + ");";
                case "Matrix3x3":
                    return "MATRIX3X3_CONV(" + parameter.Name + ");";
                case "Transform":
                    return "TRANSFORM_CONV(" + parameter.Name + ");";
                case "Vector3":
                    return "VECTOR3_CONV(" + parameter.Name + ");";
                case "Vector4":
                    return "VECTOR4_CONV(" + parameter.Name + ");";
                default:
                    return null;
            }
        }