public MethodDefinition(string name, ClassDefinition parent, int numArgs) { Name = name; Parent = parent; Parameters = new ParameterDefinition[numArgs]; if (parent != null) { parent.Methods.Add(this); } }
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; } }
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; } }
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; } }
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; } }
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; } }
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; }
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; } }
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); }
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;"); } } }
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); } }
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; } }
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; }
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); }