void WriteMethodDefinition(ManagedMethod method, int numParameters) { var nativeMethod = method.Native; var parentClass = method.Parent.Native; // Type marshalling prologue bool needTypeMarshalEpilogue = false; if (nativeMethod.Field == null) { foreach (var param in method.Parameters) { string prologue = BulletParser.GetTypeMarshalPrologueCppCli(param); if (!string.IsNullOrEmpty(prologue)) { WriteLine(1, prologue); } // Do we need a type marshalling epilogue? if (!needTypeMarshalEpilogue) { string epilogue = BulletParser.GetTypeMarshalEpilogueCppCli(param); if (!string.IsNullOrEmpty(epilogue)) { needTypeMarshalEpilogue = true; } } } } WriteTabs(1); if (nativeMethod.IsConstructor) { Write("_native = new "); } else if (!nativeMethod.IsVoid) { //if (method.ReturnType.IsBasic || method.ReturnType.Referenced != null) if (needTypeMarshalEpilogue) { // Return after epilogue (cleanup) Write($"{GetTypeName(nativeMethod.ReturnType)} ret = "); } else { // Return immediately Write("return "); } Write(BulletParser.GetTypeMarshalConstructorStart(nativeMethod)); } else if (method.Property != null && method.Equals(method.Property.Getter)) { Write(BulletParser.GetTypeMarshalConstructorStart(nativeMethod)); } // Native is defined as static_cast<className*>(_native) string nativePointer = (parentClass.BaseClass != null) ? "Native" : "_native"; if (nativeMethod.Field != null) { var property = method.Property; if (method.Equals(property.Getter)) { CachedProperty cachedProperty; if (method.Parent.CachedProperties.TryGetValue(property.Name, out cachedProperty)) { Write(cachedProperty.CacheFieldName); } else { Write($"{nativePointer}->{nativeMethod.Field.Name}"); } } else if (property.Setter != null && method.Equals(property.Setter)) { var param = method.Parameters[0]; var paramType = param.Native.Type; var fieldSet = BulletParser.GetTypeMarshalFieldSetCppCli(nativeMethod.Field, param, nativePointer); if (!string.IsNullOrEmpty(fieldSet)) { Write(fieldSet); } else { Write($"{nativePointer}->{nativeMethod.Field.Name} = "); switch (paramType.Kind) { case TypeKind.Pointer: case TypeKind.LValueReference: if (paramType.Kind == TypeKind.LValueReference) { // Dereference Write('*'); } if (paramType.Referenced.Target != null && paramType.Referenced.Target.BaseClass != null) { // Cast native pointer from base class Write($"({paramType.Referenced.FullName}*)"); } break; } Write(param.Name); if (!paramType.IsBasic) { Write("->_native"); } } } } else { if (nativeMethod.IsConstructor) { } else if (nativeMethod.IsStatic) { Write(parentClass.FullyQualifiedName + "::"); } else { Write(nativePointer + "->"); } To = WriteTo.Source; WriteMethodMarshal(method, numParameters); } if (!nativeMethod.IsConstructor && !nativeMethod.IsVoid) { Write(BulletParser.GetTypeMarshalConstructorEnd(nativeMethod)); } WriteLine(';'); // Write type marshalling epilogue if (needTypeMarshalEpilogue) { foreach (var param in method.Parameters) { string epilogue = BulletParser.GetTypeMarshalEpilogueCppCli(param); if (!string.IsNullOrEmpty(epilogue)) { WriteLine(1, epilogue); } } if (!nativeMethod.IsVoid) { WriteLine(1, "return ret;"); } } }
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); } }
void WriteMethodDefinition(MethodDefinition method, int numParameters) { var parentClass = method.Parent; // Type marshalling prologue bool needTypeMarshalEpilogue = false; if (method.Field == null) { foreach (var param in method.Parameters) { string prologue = BulletParser.GetTypeMarshalPrologueCppCli(param); if (!string.IsNullOrEmpty(prologue)) { WriteTabs(1, true); SourceWriteLine(prologue); } // Do we need a type marshalling epilogue? if (!needTypeMarshalEpilogue) { string epilogue = BulletParser.GetTypeMarshalEpilogueCppCli(param); if (!string.IsNullOrEmpty(epilogue)) { needTypeMarshalEpilogue = true; } } } } WriteTabs(1, true); if (method.IsConstructor) { SourceWrite("_native = new "); } else if (!method.IsVoid) { //if (method.ReturnType.IsBasic || method.ReturnType.Referenced != null) if (needTypeMarshalEpilogue) { // Return after epilogue (cleanup) SourceWrite(string.Format("{0} ret = ", BulletParser.GetTypeRefName(method.ReturnType))); } else { // Return immediately SourceWrite("return "); } SourceWrite(BulletParser.GetTypeMarshalConstructorStart(method)); } else if (method.Property != null && method.Equals(method.Property.Getter)) { SourceWrite(BulletParser.GetTypeMarshalConstructorStart(method)); } // Native is defined as static_cast<className*>(_native) string nativePointer = (parentClass.BaseClass != null) ? "Native" : "_native"; if (method.Field != null) { var property = method.Property; if (method.Equals(property.Getter)) { CachedProperty cachedProperty; if (method.Parent.CachedProperties.TryGetValue(property.Name, out cachedProperty)) { SourceWrite(cachedProperty.CacheFieldName); } else { SourceWrite(string.Format("{0}->{1}", nativePointer, method.Field.Name)); } } else if (property.Setter != null && method.Equals(property.Setter)) { var param = method.Parameters[0]; var fieldSet = BulletParser.GetTypeMarshalFieldSetCppCli(method.Field, param, nativePointer); if (!string.IsNullOrEmpty(fieldSet)) { SourceWrite(fieldSet); } else { SourceWrite(string.Format("{0}->{1} = ", nativePointer, method.Field.Name)); if (param.Type.IsPointer || param.Type.IsReference) { if (param.Type.IsReference) { // Dereference SourceWrite('*'); } if (param.Type.Referenced.Target != null && param.Type.Referenced.Target.BaseClass != null) { // Cast native pointer from base class SourceWrite(string.Format("({0}*)", param.Type.Referenced.FullName)); } } SourceWrite(param.ManagedName); if (!param.Type.IsBasic) { SourceWrite("->_native"); } } } } else { if (method.IsConstructor) { } else if (method.IsStatic) { SourceWrite(parentClass.FullyQualifiedName + "::"); } else { SourceWrite(nativePointer + "->"); } OutputMethodMarshal(method, numParameters); } if (!method.IsConstructor && !method.IsVoid) { SourceWrite(BulletParser.GetTypeMarshalConstructorEnd(method)); } SourceWriteLine(';'); // Write type marshalling epilogue if (needTypeMarshalEpilogue) { foreach (var param in method.Parameters) { string epilogue = BulletParser.GetTypeMarshalEpilogueCppCli(param); if (!string.IsNullOrEmpty(epilogue)) { WriteTabs(1, true); SourceWriteLine(epilogue); } } if (!method.IsVoid) { WriteTabs(1, true); SourceWriteLine("return ret;"); } } }