private IEnumerable <StatementSyntax> BuildDelegateBody(CppFunction cppFunction, TypeInfo returnTypeInfo) { yield return(SyntaxBuilder.DeclareLocals(false)); var delegates = new Dictionary <string, string>(); foreach (var cppParameter in cppFunction.Parameters) { if (!TypeMap.TryResolveType(cppParameter.Type, out var paramTypeInfo, false)) { throw new ArgumentException(); } if (!paramTypeInfo.IsFunction) { continue; } var managedParameterName = GetManagedName(cppParameter.Name); var variableName = managedParameterName + "Ptr"; delegates.Add(cppParameter.Name, variableName); yield return(SyntaxBuilder.DeclareDelegatePointerVariable(managedParameterName, variableName)); } var call = InvocationExpression(IdentifierName(GetManagedName(cppFunction.Name) + "Private")) .AddArgumentListArguments(cppFunction.Parameters.Select(BuildArgument).ToArray()); if (returnTypeInfo.IsVoid) { yield return(ExpressionStatement(call)); } else { yield return(LocalDeclarationStatement( VariableDeclaration(returnTypeInfo.TypeSyntax) .AddVariables(VariableDeclarator("result").WithInitializer( EqualsValueClause(call))))); } foreach (var cppParameter in cppFunction.Parameters.Reverse()) { if (delegates.ContainsKey(cppParameter.Name)) { var managedParameterName = GetManagedName(cppParameter.Name); yield return(SyntaxBuilder.CallKeepAlive(IdentifierName(managedParameterName))); } } if (!returnTypeInfo.IsVoid) { yield return(ReturnStatement(IdentifierName("result"))); } ArgumentSyntax BuildArgument(CppParameter cppParameter) { var name = delegates.TryGetValue(cppParameter.Name, out string paramName) ? paramName : GetManagedName(cppParameter.Name); return(Argument(IdentifierName(name))); } }