public MethodDefinition(string name, ClassDefinition parent, int numArgs)
        {
            Name = name;
            Parent = parent;
            Parameters = new ParameterDefinition[numArgs];

            if (parent != null)
            {
                parent.Methods.Add(this);
            }
        }
예제 #2
0
 public static string GetTypeMarshalFieldSetCppCli(FieldDefinition field, ParameterDefinition parameter, string nativePointer)
 {
     switch (field.Type.ManagedName)
     {
         case "Quaternion":
             return "Math::QuaternionToBtQuat(" + parameter.ManagedName + ", &" + nativePointer + "->" + field.Name + ')';
         case "Transform":
             return "Math::MatrixToBtTransform(" + parameter.ManagedName + ", &" + nativePointer + "->" + field.Name + ')';
         case "Vector3":
             return "Math::Vector3ToBtVector3(" + parameter.ManagedName + ", &" + nativePointer + "->" + field.Name + ')';
         case "Vector4":
             return "Math::Vector4ToBtVector4(" + parameter.ManagedName + ", &" + nativePointer + "->" + field.Name + ')';
         default:
             return null;
     }
 }
예제 #3
0
 public static string GetTypeMarshalEpilogueCppCli(ParameterDefinition parameter)
 {
     switch (parameter.Type.ManagedName)
     {
         case "Quaternion":
             return "QUATERNION_DEL(" + parameter.ManagedName + ");";
         case "Matrix3x3":
             return "MATRIX3X3_DEL(" + parameter.ManagedName + ");";
         case "Transform":
             return "TRANSFORM_DEL(" + parameter.ManagedName + ");";
         case "Vector3":
             return "VECTOR3_DEL(" + parameter.ManagedName + ");";
         case "Vector4":
             return "VECTOR4_DEL(" + parameter.ManagedName + ");";
         default:
             return null;
     }
 }
예제 #4
0
        public static string GetTypeMarshalEpilogue(ParameterDefinition parameter)
        {
            if (parameter.Type.IsConst || (parameter.Type.Referenced != null && parameter.Type.Referenced.IsConst))
            {
                return null;
            }

            switch (parameter.Type.ManagedName)
            {
                case "Quaternion":
                    return "QUATERNION_DEF_OUT(" + parameter.Name + ");";
                case "Matrix3x3":
                    return "MATRIX3X3_DEF_OUT(" + parameter.Name + ");";
                case "Transform":
                    return "TRANSFORM_DEF_OUT(" + parameter.Name + ");";
                case "Vector3":
                    return "VECTOR3_DEF_OUT(" + parameter.Name + ");";
                case "Vector4":
                    return "VECTOR4_DEF_OUT(" + parameter.Name + ");";
                default:
                    return null;
            }
        }
예제 #5
0
 public static string GetTypeMarshalCppCli(ParameterDefinition parameter)
 {
     switch (parameter.Type.ManagedName)
     {
         case "IDebugDraw":
             return "DebugDraw::GetUnmanaged(" + parameter.ManagedName + ")";
         case "Quaternion":
             return "QUATERNION_USE(" + parameter.ManagedName + ")";
         case "Transform":
             return "TRANSFORM_USE(" + parameter.ManagedName + ")";
         case "Matrix3x3":
             return "MATRIX3X3_USE(" + parameter.ManagedName + ")";
         case "Vector3":
             return "VECTOR3_USE(" + parameter.ManagedName + ")";
         case "Vector4":
             return "VECTOR4_USE(" + parameter.ManagedName + ")";
         default:
             return null;
     }
 }
예제 #6
0
        public static string GetTypeMarshal(ParameterDefinition parameter)
        {
            string reference = parameter.Type.IsPointer ? "&" : string.Empty;

            switch (parameter.Type.ManagedName)
            {
                case "Quaternion":
                    return reference + "QUATERNION_USE(" + parameter.Name + ")";
                case "Transform":
                    return reference + "TRANSFORM_USE(" + parameter.Name + ")";
                case "Matrix3x3":
                    return reference + "MATRIX3X3_USE(" + parameter.Name + ")";
                case "Vector3":
                    return reference + "VECTOR3_USE(" + parameter.Name + ")";
                case "Vector4":
                    return reference + "VECTOR4_USE(" + parameter.Name + ")";
                default:
                    return null;
            }
        }
예제 #7
0
        Cursor.ChildVisitResult ClassVisitor(Cursor cursor, Cursor parent)
        {
            if (cursor.Kind == CursorKind.CxxAccessSpecifier)
            {
                currentMemberAccess = cursor.AccessSpecifier;
                return Cursor.ChildVisitResult.Continue;
            }
            else if (cursor.Kind == CursorKind.CxxBaseSpecifier)
            {
                currentClass.BaseClass = new TypeRefDefinition(cursor.Type);
                return Cursor.ChildVisitResult.Continue;
            }

            if (currentMemberAccess != AccessSpecifier.Public)
            {
                return Cursor.ChildVisitResult.Continue;
            }

            if ((cursor.Kind == CursorKind.ClassDecl || cursor.Kind == CursorKind.StructDecl ||
                cursor.Kind == CursorKind.ClassTemplate || cursor.Kind == CursorKind.TypedefDecl ||
                cursor.Kind == CursorKind.EnumDecl) && cursor.IsDefinition)
            {
                ParseClassCursor(cursor);
            }
            else if (cursor.Kind == CursorKind.CxxMethod || cursor.Kind == CursorKind.Constructor)
            {
                string methodName = cursor.Spelling;
                if (excludedMethods.ContainsKey(methodName))
                {
                    return Cursor.ChildVisitResult.Continue;
                }

                currentMethod = new MethodDefinition(methodName, currentClass, cursor.NumArguments);
                currentMethod.ReturnType = new TypeRefDefinition(cursor.ResultType);
                currentMethod.IsStatic = cursor.IsStaticCxxMethod;
                currentMethod.IsConstructor = cursor.Kind == CursorKind.Constructor;

                if (cursor.IsVirtualCxxMethod)
                {
                    currentMethod.IsVirtual = true;
                    if (cursor.IsPureVirtualCxxMethod)
                    {
                        currentMethod.IsAbstract = true;
                        currentClass.IsAbstract = true;
                    }
                }

                // Check if the return type is a template
                cursor.VisitChildren(MethodTemplateTypeVisitor);

                // Parse arguments
                for (uint i = 0; i < cursor.NumArguments; i++)
                {
                    Cursor arg = cursor.GetArgument(i);

                    string parameterName = arg.Spelling;
                    if (parameterName.Length == 0)
                    {
                        parameterName = "__unnamed" + i;
                    }
                    currentParameter = new ParameterDefinition(parameterName, new TypeRefDefinition(arg.Type));
                    currentMethod.Parameters[i] = currentParameter;
                    arg.VisitChildren(MethodTemplateTypeVisitor);
                    currentParameter = null;

                    // Check if it's a const or optional parameter
                    IEnumerable<Token> argTokens = currentTU.Tokenize(arg.Extent);
                    foreach (Token token in argTokens)
                    {
                        if (token.Spelling.Equals("="))
                        {
                            currentMethod.Parameters[i].IsOptional = true;
                        }
                    }
                }

                currentMethod = null;
            }
            else if (cursor.Kind == CursorKind.FieldDecl)
            {
                currentField = new FieldDefinition(cursor.Spelling,
                    new TypeRefDefinition(cursor.Type), currentClass);
                currentFieldHasSpecializedParameter = false;
                cursor.VisitChildren(FieldTemplateTypeVisitor);
                currentField = null;
            }
            else if (cursor.Kind == CursorKind.UnionDecl)
            {
                return Cursor.ChildVisitResult.Recurse;
            }
            else
            {
                //Console.WriteLine(cursor.Spelling);
            }
            return Cursor.ChildVisitResult.Continue;
        }
        private string GetParameterTypeNameCS(ParameterDefinition param)
        {
            var type = param.Type;
            string typeName = GetTypeNameCS(type);

            switch (param.MarshalDirection)
            {
                case MarshalDirection.Out:
                    return $"out {typeName}";
                case MarshalDirection.InOut:
                    type = type.Canonical;
                    if (type.Kind == TypeKind.LValueReference)
                    {
                        var referencedType = type.Referenced.Canonical;
                        if (referencedType.IsBasic ||
                            (referencedType.Target != null && referencedType.Target.MarshalAsStruct))
                        {
                            return "ref " + typeName;
                        }
                    }
                    break;
            }

            return typeName;
        }
예제 #9
0
 public static string GetFieldSetterMarshal(ParameterDefinition parameter, FieldDefinition field)
 {
     switch (parameter.Type.ManagedName)
     {
         case "Quaternion":
             return "QUATERNION_IN(" + parameter.Name + ", &obj->" + field.Name + ");";
         case "Matrix3x3":
             return "MATRIX3X3_IN(" + parameter.Name + ", &obj->" + field.Name + ");";
         case "Transform":
             return "TRANSFORM_IN(" + parameter.Name + ", &obj->" + field.Name + ");";
         case "Vector3":
             return "VECTOR3_IN(" + parameter.Name + ", &obj->" + field.Name + ");";
         case "Vector4":
             return "VECTOR4_IN(" + parameter.Name + ", &obj->" + field.Name + ");";
         default:
             return null;
     }
 }
예제 #10
0
        public string GetManagedParameterName(ParameterDefinition param)
        {
            if (parameterNameMapping.ContainsKey(param.Name))
            {
                return parameterNameMapping[param.Name];
            }

            string managedName = param.Name;
            if (managedName.StartsWith("__unnamed"))
            {
                return managedName;
            }

            if (managedName.Length == 1)
            {
                return managedName.ToLower();
            }

            // Remove underscores
            // one_two_three -> oneTwoThree
            while (managedName.Contains("_"))
            {
                int pos = managedName.IndexOf('_');
                if (pos == 0)
                {
                    managedName = managedName.Substring(1);
                }
                else if (pos >= managedName.Length - 1)
                {
                    managedName = managedName.Substring(0, pos);
                    break;
                }
                else
                {
                    managedName = managedName.Substring(0, pos) + managedName.Substring(pos + 1, 1).ToUpper() + managedName.Substring(pos + 2);
                }
            }
            return managedName;
        }
        string GetManagedParameterName(ParameterDefinition param)
        {
            if (Project.ParameterNameMapping != null)
            {
                string mapping = Project.ParameterNameMapping.Map(param.Name);
                if (mapping != null) return mapping;
            }

            string managedName = param.Name;
            if (managedName.StartsWith("__unnamed"))
            {
                return managedName;
            }

            return ToCamelCase(param.Name, false);
        }
예제 #12
0
        void WriteMethodDefinition(MethodDefinition method, int numParameters, int overloadIndex, int level,
                                   ParameterDefinition outValueParameter)
        {
            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}";
                // TODO:
                if (field.Type.Target != null && field.Type.Target.MarshalAsStruct)
                {
                    string macroPrefix = field.Type.Name.ToUpper();
                    string paramName   = (outValueParameter != null ? 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 (outValueParameter != null)
                    {
                        string macroPrefix = outValueParameter.Type.Referenced.Name.ToUpper();
                        if (returnType.Kind == TypeKind.LValueReference)
                        {
                            Write($"{macroPrefix}_COPY({outValueParameter.Name}, &");
                        }
                        else
                        {
                            Write($"{macroPrefix}_SET({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 (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;");
                }
            }
        }
예제 #13
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;
            }

            // Can't return whole structures, so use an output parameter
            // referencing the struct that will hold the return value.
            // "v method()" -> "void method(v* value)"
            // "v& method()" -> "void method(v* value)"
            ParameterDefinition outValueParameter = null;
            var returnType = method.ReturnType;

            if ((returnType.Target != null && returnType.Target.MarshalAsStruct) ||
                (returnType.Kind == TypeKind.LValueReference && returnType.Referenced.Target != null && returnType.Referenced.Target.MarshalAsStruct))
            {
                var valueType = new TypeRefDefinition
                {
                    Kind       = TypeKind.Pointer,
                    Referenced = (returnType.Kind == TypeKind.LValueReference ? returnType.Referenced : returnType).Copy()
                };
                valueType.Referenced.IsConst = false;
                // TODO:

                /*
                 * 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";
                 * }
                 *
                 * outValueParameter = new ParameterDefinition(paramName, valueType)
                 * {
                 *  ManagedName = paramName,
                 *  MarshalDirection = MarshalDirection.Out
                 * };
                 */
            }

            EnsureWhiteSpace(WriteTo.Source);

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

            WriteMethodDeclaration(method, numParameters, level, overloadIndex, outValueParameter);

            // Method body
            WriteLine('{', WriteTo.Source);
            WriteMethodDefinition(method, numParameters, overloadIndex, level, outValueParameter);
            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);
            }
        }
예제 #14
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;
            }
        }
예제 #15
0
 public static string GetReturnValueMarshalEnd(ParameterDefinition param)
 {
     switch (param.Type.ManagedName)
     {
         case "Quaternion":
         case "Matrix3x3":
         case "Transform":
         case "Vector3":
         case "Vector4":
             return "), " + param.Name + ");";
         default:
             return null;
     }
 }
        private string GetParameterMarshal(ParameterDefinition param)
        {
            var typeName = GetTypeName(param.Type);
            var type = param.Type.Canonical;

            switch (type.Kind)
            {
                case TypeKind.Pointer:
                case TypeKind.LValueReference:
                    if (type.Referenced.Target != null && type.Referenced.Target.MarshalAsStruct)
                    {
                        // https://msdn.microsoft.com/en-us/library/77e6taeh%28v=vs.100%29.aspx
                        // Default IDL attribute values:
                        // ref - [In, Out]
                        // out - [Out]
                        switch (param.MarshalDirection)
                        {
                            case MarshalDirection.Out:
                                return $"[Out] {typeName}%";
                            case MarshalDirection.InOut:
                                return $"{typeName}%";
                            case MarshalDirection.In:
                                return typeName;
                        }
                    }
                    break;
            }

            if (type.Kind == TypeKind.LValueReference && type.Referenced.Canonical.IsBasic)
            {
                typeName = GetTypeName(type.Referenced);
                switch (param.MarshalDirection)
                {
                    case MarshalDirection.Out:
                        return $"[Out] {typeName}%";
                    case MarshalDirection.InOut:
                        return $"{typeName}%";
                    case MarshalDirection.In:
                        return typeName;
                }
            }

            return typeName;
        }
예제 #17
0
        public static string GetTypeCSMarshal(ParameterDefinition parameter)
        {
            var type = parameter.Type;

            if (type.Referenced != null && !type.IsBasic)
            {
                switch (type.ManagedNameCS)
                {
                    case "Matrix3x3":
                    case "Quaternion":
                    case "Transform":
                    case "Vector3":
                    case "Vector4":
                        {
                            if (type.Referenced != null && !(type.IsConst || type.Referenced.IsConst))
                            {
                                return "out " + parameter.ManagedName;
                            }
                            return "ref " + parameter.ManagedName;
                        }
                    case "IDebugDraw":
                        return "DebugDraw.GetUnmanaged(" + parameter.ManagedName + ')';
                }
            }

            if (!type.IsBasic)
            {
                if (!(type.IsPointer && type.ManagedName.Equals("void")))
                {
                    return parameter.ManagedName + "._native";
                }
            }
            return parameter.ManagedName;
        }
        private string GetParameterTypeNameDllImport(ParameterDefinition param)
        {
            var type = param.Type.Canonical;
            switch (type.Kind)
            {
                case TypeKind.Pointer:
                case TypeKind.LValueReference:
                    if (type.Referenced.Target != null && type.Referenced.Target.MarshalAsStruct)
                    {
                        var typeName = GetTypeNameCS(type);

                        // https://msdn.microsoft.com/en-us/library/77e6taeh%28v=vs.100%29.aspx
                        // Default IDL attribute values:
                        // ref - [In, Out]
                        // out - [Out]
                        switch (param.MarshalDirection)
                        {
                            case MarshalDirection.In:
                                return $"[In] ref {typeName}";
                            case MarshalDirection.InOut:
                                return $"ref {typeName}";
                            case MarshalDirection.Out:
                                return $"out {typeName}";
                        }
                    }
                    break;
            }

            if (type.Kind == TypeKind.LValueReference && type.Referenced.Canonical.IsBasic)
            {
                switch (param.MarshalDirection)
                {
                    case MarshalDirection.Out:
                        return $"out {GetTypeNameCS(type.Referenced.Canonical)}";
                    case MarshalDirection.InOut:
                        return $"ref {GetTypeNameCS(type.Referenced.Canonical)}";
                    case MarshalDirection.In:
                        return GetTypeNameCS(type.Referenced.Canonical);
                }
            }

            if (type.Referenced != null)
            {
                return "IntPtr";
            }

            return GetTypeNameCS(type);
        }
        string GetManagedParameterName(ParameterDefinition param)
        {
            string mapping = Project.ParameterNameMapping?.Map(param.Name);
            if (mapping != null) return mapping;

            switch (param.Name)
            {
                case "out":
                    return $"@{param.Name}";
            }

            return ToCamelCase(param.Name, false);
        }