public void Enter(CppFunction cpp_fn) { var scope = new Scope(cpp_fn); scopes.Add(scope); functions.Add(cpp_fn); }
public CsFunction Prepare(CppFunction cppFunction) { var cSharpFunction = new CsFunction(cppFunction); // All functions must have a tag var tag = cppFunction.GetMappingRule(); if (tag == null || tag.Group == null) { Logger.Error(LoggingCodes.FunctionNotAttachedToGroup, "CppFunction [{0}] is not tagged and attached to any Class/FunctionGroup", cppFunction); return(null); } var csClass = groupRegistry.FindGroup(tag.Group); if (csClass == null) { Logger.Error(LoggingCodes.FunctionNotAttachedToGroup, "CppFunction [{0}] is not attached to a Class/FunctionGroup", cppFunction); return(null); } // Set the DllName for this function cSharpFunction.DllName = tag.FunctionDllName; // Add the function to the ClassType csClass.Add(cSharpFunction); return(cSharpFunction); }
public CsFunction(Ioc ioc, CppFunction cppFunction, string name) : base(ioc, cppFunction, name) { var tag = cppFunction.Rule; // Set the DllName for this function DllName = tag.FunctionDllName; }
public static CSharpElement ConvertFunction(CSharpConverter converter, CppFunction cppFunction, CSharpElement context) { // We process only public export functions if (!cppFunction.IsPublicExport() || ((cppFunction.Flags & (CppFunctionFlags.Inline | CppFunctionFlags.Method | CppFunctionFlags.Constructor | CppFunctionFlags.Destructor)) != 0 && (cppFunction.Flags & CppFunctionFlags.Virtual) == 0)) { return(null); } // Register the struct as soon as possible var csFunction = new CSharpMethod() { CppElement = cppFunction }; var container = converter.GetCSharpContainer(cppFunction, context); converter.ApplyDefaultVisibility(csFunction, container); container.Members.Add(csFunction); converter.AddUsing(container, "System.Runtime.InteropServices"); if ((cppFunction.Flags & CppFunctionFlags.Virtual) == 0) { csFunction.Modifiers |= CSharpModifiers.Static | CSharpModifiers.Extern; } else { csFunction.Visibility = CSharpVisibility.None; } csFunction.Name = converter.GetCSharpName(cppFunction, csFunction); csFunction.Comment = converter.GetCSharpComment(cppFunction, csFunction); csFunction.ReturnType = converter.GetCSharpType(cppFunction.ReturnType, csFunction); return(csFunction); }
private CppFunction GetCppFunction(CXType functionType, CXCursor cursor, string functionName) { var function = new CppFunction(); var returnType = clang.getResultType(functionType); function.Name = functionName; function.Comment = clang.Cursor_getBriefCommentText(cursor).ToString(); var returnParam = GetFunctionParamMarshalType(returnType); function.ReturnType = returnParam.Type; uint i = 0; clang.visitChildren(cursor, (cursorParam, cxCursor1, ptr) => { if (cursorParam.kind == CXCursorKind.CXCursor_ParmDecl) { var argName = clang.getCursorSpelling(cursorParam).ToString(); if (string.IsNullOrEmpty(argName)) { argName = "param" + i; } var parameter = GetFunctionParamMarshalType(clang.getArgType(functionType, i)); parameter.Name = argName; parameter.Type = parameter.Type.Replace("const ", string.Empty); function.Parameters.Add(parameter); i++; } return(CXChildVisitResult.CXChildVisit_Continue); }, new CXClientData(IntPtr.Zero)); return(function); }
/// <summary> /// E.g.: "void Foo(int age, char* name)" ==> "ic" (first letters of parameters' types) /// </summary> public static string ParametersMask(this CppFunction function) { var sb = new StringBuilder(); var parameters = function.Parameters.ToList(); if (parameters.Count < 1) { sb.Append("0"); } else { foreach (var p in parameters) { var type = p.Type.GetDisplayName() .Replace("const ", "") .Replace("*", "") .Replace("&", "") .Trim(); sb.Append(type[0]); } } return(sb.ToString()); }
public void RegisterCandidates(TypeMapper mapper, List <CppFunction> functions) { string[] prefixes = { "Is", "Has", "Get" }; foreach (var f in functions) { var pi = new PropertyInfo(mapper); string name = mapper.RenameForApi(f.Name, true); string prefix = prefixes.FirstOrDefault(p => name.StartsWith(p)); if (prefix != null) { if (f.Parameters.Count == 0 && !f.IsConstructor) { pi.GetterFunction = f; pi.GettetApiName = name; pi.PropertyName = name.Remove(0, prefix.Length); // looking for setter: CppFunction setter = functions.FirstOrDefault(sf => sf.Parameters.Count == 1 && mapper.RenameForApi(sf.Name, true).StartsWith("Set")); if (setter != null && f.IsStatic() == setter.IsStatic() && !setter.IsConstructor) { pi.SetterFunction = setter; pi.SetterApiName = mapper.RenameForApi(setter.Name, true); } } } _candidates.Add(pi); } }
/// <summary> /// Deals with turning the CppFunction types into V types, function name to snake case, params /// to snake case and any other data transformations we will need for the V functions /// </summary> static ParsedFunction ParsedFunctionFromCppFunction(CppFunction cFunc, Config config) { var f = new ParsedFunction { Name = cFunc.Name, VName = V.ToSnakeCase(config.StripFunctionPrefix(cFunc.Name)) }; // hack to fix ghetto forced 'init' module function if (f.VName == "init") { f.VName = config.ModuleName + "_" + f.VName; } if (cFunc.ReturnType.GetDisplayName() != "void") { f.RetType = cFunc.ReturnType.GetDisplayName(); f.VRetType = V.GetVType(cFunc.ReturnType); } foreach (var param in cFunc.Parameters) { var p = new ParsedParameter { Name = param.Name.EscapeReserved(), VName = V.ToSnakeCase(config.StripFunctionPrefix(param.Name)).EscapeReserved(), Type = param.Type.GetDisplayName(), VType = V.GetVType(param.Type) }; f.Parameters.Add(p); } return(f); }
public static object GetParametersSignature(CppFunction command, bool useTypes = true) { StringBuilder signature = new StringBuilder(); foreach (var parameter in command.Parameters) { string convertedType = ConvertToCSharpType(parameter.Type); // Hack for structs that are not bittable // https://stackoverflow.com/questions/32110152/c-sharp-marshalling-bool if (convertedType == "WGPURenderPipelineDescriptor*" || convertedType == "WGPUBufferDescriptor*") { signature.Append("ref "); convertedType = convertedType.Remove(convertedType.Length - 1); } string convertedName = parameter.Name; if (useTypes) { signature.Append($"{convertedType} "); } signature.Append($"{convertedName}, "); } signature.Length -= 2; return(signature.ToString()); }
internal bool IsMethodMarkedAsUnsupported(CppFunction function) { if (function.Parent is CppClass cppClass) { return(_unsupportedMethods.Contains(cppClass.GetDisplayName() + "." + function.Name)); } return(_unsupportedMethods.Contains(function.Name)); }
public static bool IsCopyConstructor(this CppFunction function) { if (!function.IsConstructor || function.Parameters.Count != 1) { return(false); } var p = function.Parameters[0].Type.GetDisplayName(); return(p.StartsWith("const ") && p.Contains("&")); // TODO: }
public static ExpressionStatementSyntax EmitCalli(TypeInfo returnTypeInfo, CppFunction cppFunction, TypeMap typeMap, IReadOnlyDictionary <string, string> delegates) { return(ExpressionStatement( InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName("IL"), IdentifierName("Emit")), IdentifierName("Calli")), ArgumentList(SingletonSeparatedList(Argument( ObjectCreationExpression( IdentifierName("StandAloneMethodSig"), ArgumentList(SeparatedList(GetMethodSigParameters())), null))))))); IEnumerable <ArgumentSyntax> GetMethodSigParameters() { yield return(Argument( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName(nameof(CallingConvention)), IdentifierName(nameof(CallingConvention.Cdecl))))); if (returnTypeInfo.IsFunction) { yield return(Argument(TypeOfExpression(IntPtrName))); } else { yield return(Argument(TypeOfExpression(returnTypeInfo.TypeSyntax))); } foreach (var cppParameter in cppFunction.Parameters) { if (delegates.TryGetValue(cppParameter.Name, out _)) { yield return(Argument(TypeOfExpression(IdentifierName(nameof(IntPtr))))); } else if (typeMap.TryResolveType(cppParameter.Type, out var paramTypeInfo)) { yield return(Argument(TypeOfExpression(paramTypeInfo.TypeSyntax))); } else { throw new ArgumentException(); } } } }
private void WriteFunction(CppFunction function) { var signature = new StringBuilder(); if (!string.IsNullOrWhiteSpace(function.Comment)) { WriteComment(function.Comment); } var isPrivate = PrivateFunctions.Contains(function.Name); signature.Append((isPrivate ? "private " : "public ") + "static extern "); // Function return type signature.Append(function.ReturnType); signature.Append(" "); var functionName = function.Name + (isPrivate ? "Internal" : string.Empty); // Function name signature.Append(functionName); signature.Append("("); for (var j = 0; j < function.Parameters.Count; j++) { var parameter = function.Parameters[j]; if (j > 0) { signature.Append(", "); } if (parameter.Attributes != null) { signature.Append(parameter.Attributes).Append(" "); } //if (!marshal && j == 0 && handles.Contains(parameter.Type)) // signature.Append("this "); if (parameter.Qualifier != null) { signature.Append(parameter.Qualifier).Append(" "); } signature.Append(parameter.Type); signature.Append(" "); signature.Append(parameter.Name); } signature.Append(")"); WriteLine( $"[DllImport(LibSassDll, EntryPoint = \"{function.Name}\",CallingConvention = CallingConvention.Cdecl)]"); WriteLine(signature + ";"); }
public Scope(CppFunction cpp_func) { cpp_item = cpp_func; type = Type.Function; get_name = () => { return(cpp_func.Name); }; get_unique_name = () => { // cpp_func.TemplateParameters return(""); }; }
/// <summary> /// Gets a boolean indicating whether the function is a dllexport or visibility("default") /// </summary> /// <param name="function">The function to check against</param> /// <returns><c>true</c> if the function is a dllexport or visibility("default")</returns> public static bool IsPublicExport(this CppFunction function) { if (function.Attributes != null) { foreach (var attr in function.Attributes) { if (attr.IsPublicExport()) { return(true); } } } return(function.LinkageKind == CppLinkageKind.External || function.LinkageKind == CppLinkageKind.UniqueExternal); }
public static object GetParametersSignature(CppFunction command, bool useTypes = true) { StringBuilder signature = new StringBuilder(); foreach (var parameter in command.Parameters) { string convertedType = ConvertToCSharpType(parameter.Type); string convertedName = parameter.Name; if (useTypes) { signature.Append($"{convertedType} "); } signature.Append($"{convertedName}, "); } signature.Length -= 2; return(signature.ToString()); }
private static void EmitInvoke( CodeWriter writer, CppFunction function, List <string> parameters, bool handleCheckResult = true) { var postCall = string.Empty; if (handleCheckResult) { var hasResultReturn = GetCsTypeName(function.ReturnType) == "VkResult"; if (hasResultReturn) { postCall = ".CheckResult()"; } } var index = 0; var callArgumentStringBuilder = new StringBuilder(); foreach (var parameterName in parameters) { callArgumentStringBuilder.Append(parameterName); if (index < parameters.Count - 1) { callArgumentStringBuilder.Append(", "); } index++; } var callArgumentString = callArgumentStringBuilder.ToString(); writer.WriteLine($"{function.Name}({callArgumentString}){postCall};"); }
public static bool IsOperator(this CppFunction func) => func.Name.StartsWith("operator"); // TODO: regex? public static bool IsStatic(this CppFunction func) => func.StorageQualifier == CppStorageQualifier.Static;
public static bool IsOperator(this CppFunction func) => func.Name.StartsWith("operator"); // TODO: regex?
private void DefineFunction(CodeType typeDecl, CppFunction func) { if (func.Name == "ArraySizeHelper") { return; } if (func.LinkageKind != CppLinkageKind.External) { throw new NotImplementedException(); } TypeDesc retType = GetTypeDesc(func.ReturnType); var fn = new CodeMethod(func.Name); fn.RetVal = new CodeMethodParameter(null) { Type = ResolveCefType(retType.ToString()) }; fn.Attributes = CodeAttributes.Public | CodeAttributes.External | CodeAttributes.Unsafe | CodeAttributes.Static; if (func.CallingConvention == CppCallingConvention.C) { fn.CustomAttributes.AddDllImportfAttribute(CallingConvention.Cdecl); } else if (func.CallingConvention == CppCallingConvention.X86StdCall) { fn.CustomAttributes.AddDllImportfAttribute(CallingConvention.StdCall); } else { throw new NotImplementedException(); } string filename = func.Span.Start.File; filename = Path.GetRelativePath(BaseDirectory, filename).Replace('\\', '/'); fn.Comments.AddVSDocComment(func.Comment, "summary"); fn.Comments.AddVSDocComment(string.Format("Defined in {0} as\n{1}", filename, func.ToString()), "remarks"); CppContainerList <CppParameter> @params = func.Parameters; for (int i = 0; i < @params.Count; i++) { CppParameter arg = @params[i]; var param = new CodeMethodParameter(arg.Name.EscapeName()); TypeDesc paramType = GetTypeDesc(arg.Type); string argType = paramType.ToString(); while (argType.StartsWith("const ")) { argType = argType.Substring(6); param.Direction = CodeMethodParameterDirection.In; } param.Type = ResolveCefType(argType); fn.Parameters.Add(param); } typeDecl.Members.Add(fn); }
public static string GetParameterSignature(CppFunction cppFunction, bool canUseOut) { return(GetParameterSignature(cppFunction.Parameters, canUseOut)); }
public CsFunction(CppFunction cppMethod) : base(cppMethod) { }
public PropertyInfo AsPropertyCandidate(CppFunction function) { return(_candidates.FirstOrDefault(c => c.GetterFunction == function || c.SetterFunction == function)); }
public CsFunction(CppFunction cppFunction) : base(cppFunction) { }
public void Basic() { var config = new ConfigFile { Id = nameof(Basic), Namespace = nameof(Basic), Includes = { new IncludeRule { Attach = true, File = "func.h", Namespace = nameof(Basic) } }, Extension = { new CreateExtensionRule { NewClass = $"{nameof(Basic)}.Functions", } }, Bindings = { new BindRule("int", "System.Int32") }, Mappings = { new MappingRule { Function = "Test", FunctionDllName = "\"Test.dll\"", Group = $"{nameof(Basic)}.Functions" } } }; var function = new CppFunction("Test") { ReturnValue = new CppReturnValue { TypeName = "int", } }; var include = new CppInclude("func"); var module = new CppModule("SharpGenTestModule"); include.Add(function); module.Add(include); var(solution, _) = MapModel(module, config); Assert.Single(solution.EnumerateDescendants <CsGroup>()); var group = solution.EnumerateDescendants <CsGroup>().First(); Assert.Equal("Functions", group.Name); Assert.Single(group.Functions); var csFunc = group.Functions.First(); Assert.Equal(TypeRegistry.Int32, csFunc.ReturnValue.PublicType); Assert.Empty(csFunc.Parameters); Assert.Equal(Visibility.Static, csFunc.Visibility & Visibility.Static); }
/// <summary> /// <param name="function">Function we about to generate [DllImport] for</param> /// <param name="cname">Exact C name</param> /// </summary> public static (string, string) GenerateMethodCSharp(CppFunction function, string cname) { var dllImportSb = new StringBuilder(); var apiDefinitionSb = new StringBuilder(); var apiImplSb = new StringBuilder(); bool castToBool = false; // for cases when we a method returns non-blittable bools bool isStatic = function.StorageQualifier == CppStorageQualifier.Static; List <CppParameter> parameters = function.Parameters; apiDefinitionSb.Append("public"); if (isStatic) { apiDefinitionSb.Append(" static"); } dllImportSb.Append(Tabs(2)).Append($"[DllImport({MainClassName}.NativeLib, CallingConvention=CallingConvention.Cdecl)]\n"); dllImportSb.Append(Tabs(2)).Append("private static extern "); apiImplSb.Append(" => "); if (function.IsConstructor) { dllImportSb.Append("void*"); } else { var returnTypeCs = RemapTypeToCSharp(function.ReturnType.GetDisplayName()); var returnTypeApiCs = returnTypeCs; if (returnTypeCs == "nint") // HACK - I want bindings to be Any CPU and don't want to expose IntPtr. { returnTypeApiCs = returnTypeCs = "long"; apiImplSb.Append("(long)"); // cast to long } if (returnTypeCs == "bool") { // bool is not blittable castToBool = true; returnTypeCs = "byte"; } dllImportSb.Append(returnTypeCs); apiDefinitionSb.Append(" ").Append(returnTypeApiCs); } dllImportSb.Append($" {cname}("); string apiName = ToCamelCase(function.Name); // ugly hacks if (isStatic && apiName == "IsObjectOrArray") { apiName = "IsObjectOrArrayStatic"; } if (apiName == "GetType") { apiName = "GetTokenType"; } if (function.IsConstructor) { if (function.Parent is CppClass cppClass) { apiName = RemapTypeToCSharp(cppClass.Name); } else { apiName = MainClassName; // Class for global functions } } apiDefinitionSb.Append($" {apiName}"); bool convertedToProperty = false; if (function.Name.StartsWith("is") && parameters.Count == 0 && !function.IsConstructor) { convertedToProperty = true; } else { apiDefinitionSb.Append("("); } if (function.IsConstructor) { apiImplSb.Append($"this.Handle = {cname}("); } else { apiImplSb.Append($"{cname}("); } if (!function.IsConstructor && !isStatic) { dllImportSb.Append("void* target"); apiImplSb.Append("this.Handle"); if (parameters.Count > 0) { dllImportSb.Append(", "); apiImplSb.Append(", "); } } for (var i = 0; i < parameters.Count; i++) { CppParameter parameter = parameters[i]; // TODO: extract default value if any bool isWrapper = false; var ctype = parameter.Type.GetDisplayName(); if (_allClassNames.Any(c => ctype.Contains(c))) { isWrapper = true; } var paramTypeNameCs = RemapTypeToCSharp(parameter.Type.GetDisplayName()); var paramTypePinvokeCs = paramTypeNameCs; if (paramTypeNameCs == "nint") { paramTypeNameCs = "long"; paramTypePinvokeCs = "IntPtr"; apiImplSb.Append("(IntPtr)"); // cast to IntPtr } dllImportSb.Append(isWrapper ? "void*" : paramTypePinvokeCs); dllImportSb.Append(" "); dllImportSb.Append(parameter.Name); apiDefinitionSb.Append(paramTypeNameCs); apiDefinitionSb.Append(" "); apiDefinitionSb.Append(parameter.Name); apiImplSb.Append(parameter.Name); if (isWrapper) { apiImplSb.Append(".Handle"); } if (i < parameters.Count - 1) { dllImportSb.Append(", "); apiDefinitionSb.Append(", "); apiImplSb.Append(", "); } } dllImportSb.Append(");"); if (!convertedToProperty) { apiDefinitionSb.Append(")"); } if (castToBool) { apiImplSb.AppendLine(") > 0;"); } else { apiImplSb.AppendLine(");"); } return(dllImportSb.ToString(), $"{GenerateCommentsSummary(2, function.Comment)}{Tabs(2)}{apiDefinitionSb}{apiImplSb}"); }
private static void GenerateCommands(CppCompilation compilation, string outputPath) { // Generate Functions using var writer = new CodeWriter(Path.Combine(outputPath, "Commands.cs"), "System", "Vortice.Mathematics" ); var commands = new Dictionary <string, CppFunction>(); var instanceCommands = new Dictionary <string, CppFunction>(); var deviceCommands = new Dictionary <string, CppFunction>(); foreach (CppFunction?cppFunction in compilation.Functions) { string?returnType = GetCsTypeName(cppFunction.ReturnType, false); bool canUseOut = s_outReturnFunctions.Contains(cppFunction.Name); string?csName = cppFunction.Name; string?argumentsString = GetParameterSignature(cppFunction, canUseOut); commands.Add(csName, cppFunction); if (cppFunction.Parameters.Count > 0) { var firstParameter = cppFunction.Parameters[0]; if (firstParameter.Type is CppTypedef typedef) { if (typedef.Name == "VkInstance" || typedef.Name == "VkPhysicalDevice" || IsInstanceFunction(cppFunction.Name)) { instanceCommands.Add(csName, cppFunction); } else { deviceCommands.Add(csName, cppFunction); } } } } using (writer.PushBlock($"unsafe partial class Vulkan")) { foreach (KeyValuePair <string, CppFunction> command in commands) { CppFunction cppFunction = command.Value; if (cppFunction.Name == "vkCmdSetBlendConstants") { } writer.WriteLine($"private static IntPtr {command.Key}_ptr;"); writer.WriteLine($"[Calli]"); var returnType = GetCsTypeName(cppFunction.ReturnType, false); bool canUseOut = s_outReturnFunctions.Contains(cppFunction.Name); var argumentsString = GetParameterSignature(cppFunction, canUseOut); using (writer.PushBlock($"public static {returnType} {cppFunction.Name}({argumentsString})")) { writer.WriteLine("throw new NotImplementedException();"); } writer.WriteLine(); } WriteCommands(writer, "GenLoadInstance", instanceCommands); WriteCommands(writer, "GenLoadDevice", deviceCommands); } }
/// <param name="dllImportPath">will be used as the first argument in [DllImport]. Can be a path to some constant</param> /// <param name="generateCForGlobalFunctions">sometimes global functions are ready to be pinvoked as is</param> public static void Generate(TypeMapper mapper, TemplateManager templateManager, string @namespace, string dllImportPath, string outCFile, string outCsFile, bool generateCForGlobalFunctions = true) { var csFileSb = new StringBuilder(); var cFileSb = new StringBuilder(); foreach (CppClassContainer cppClass in mapper.GetAllClasses()) { var csClassSb = new StringBuilder(); List <CppFunction> allFunctions = cppClass.Functions; for (int i = 0; i < allFunctions.Count; i++) { CppFunction function = allFunctions[i]; if (!mapper.IsSupported(function.ReturnType.GetDisplayName()) || !function.Parameters.All(p => mapper.IsSupported(p.Type.GetDisplayName())) || function.IsOperator()) { Logger.LogWarning($"Ignoring {function.Name}"); // we can't bind this method (yet) continue; } // Type_MethodName1 string flatFunctionName = $"{cppClass.Name}_{function.Name}{i}"; if (!generateCForGlobalFunctions) { flatFunctionName = function.Name; // we are going to pinvoke it directly } var cfunctionWriter = new FunctionWriter(); var dllImportWriter = new FunctionWriter(); // TODO: apiFunctionWriter = new FunctionWriter(); dllImportWriter.Attribute($"[DllImport({dllImportPath}, CallingConvention = CallingConvention.Cdecl)]") .Private().Static().Extern(); if (function.IsConstructor) { cfunctionWriter.ReturnType(cppClass.Class.GetFullTypeName() + "*", "EXPORTS"); dllImportWriter.ReturnType(nameof(IntPtr)); } else { var funcReturnType = function.ReturnType.GetFullTypeName(); cfunctionWriter.ReturnType(funcReturnType, "EXPORTS"); dllImportWriter.ReturnType(mapper.MapToManagedType(funcReturnType)); } // PS: should we generate C for global functions (we currently do)? probably it should be optional cfunctionWriter.MethodName(flatFunctionName); dllImportWriter.MethodName(flatFunctionName); if (!function.IsConstructor && !function.IsStatic() && !cppClass.IsGlobal) { // all instance methods will have "this" as the first argument cfunctionWriter.Parameter(cppClass.Class.GetFullTypeName() + "*", "target"); dllImportWriter.Parameter(nameof(IntPtr), "target"); } foreach (var parameter in function.Parameters) { cfunctionWriter.Parameter( parameter.Type.GetDisplayName(), parameter.Name); dllImportWriter.Parameter( mapper.MapToManagedType(parameter.Type.GetDisplayName()), mapper.EscapeVariableName(parameter.Name)); } // append "return" if needed cfunctionWriter.BodyStart(); if (cppClass.IsGlobal) { // GlobalMethod cfunctionWriter.BodyCallMethod(function.Name); } else if (!function.IsConstructor && !function.IsStatic()) { // target->InstanceMethod cfunctionWriter.BodyCallMethod($"target->{function.Name}"); } else if (function.IsStatic()) { // Class1::StaticMethod cfunctionWriter.BodyCallMethod(cppClass.Class.GetFullTypeName() + "::" + function.Name); } else { // new Class1 cfunctionWriter.BodyCallMethod($"new {cppClass.Class.GetFullTypeName()}"); } foreach (var parameter in function.Parameters) { cfunctionWriter.PassParameter(parameter.Name); } csClassSb.AppendLine(dllImportWriter.BuildWithoutBody().Tabify(2)); csClassSb.AppendLine(); cFileSb.AppendLine(cfunctionWriter.Build()); cFileSb.AppendLine(); } if (cppClass.IsGlobal && generateCForGlobalFunctions) { csFileSb.Append(templateManager.CSharpGlobalClass(csClassSb.ToString(), dllImportPath)); } else if (!cppClass.IsGlobal) { csFileSb.Append(templateManager.CSharpClass(cppClass.Name, cppClass.Name, csClassSb.ToString(), dllImportPath)); } } File.WriteAllText(outCFile, templateManager.CHeader() + cFileSb); File.WriteAllText(outCsFile, templateManager.CSharpHeader(@namespace, csFileSb.ToString())); }