private ParameterSyntax BuildParameter(CppParameter cppParameter, bool convertConstCharPtr, bool useFunctionPointers = false) { var name = Identifier(GetManagedName(cppParameter.Name)); if (TypeMap.TryResolveType(cppParameter.Type, out var typeInfo)) { if (convertConstCharPtr && typeInfo.CppType.IsConstCharPtr()) { return(Parameter(name) .WithType(SyntaxBuilder.BuildReadOnlySpanName(SyntaxKind.CharKeyword)) .AddModifiers(Token(SyntaxKind.InKeyword))); } if (useFunctionPointers && typeInfo.IsFunction) { return(Parameter(name).WithType(SyntaxBuilder.IntPtrName)); } return(Parameter(name).WithType(typeInfo.TypeSyntax)); } if (Debugger.IsAttached) { Debugger.Break(); } throw new NotSupportedException(); }
private MemberDeclarationSyntax BuildField(CppField cppField) { if (TypeMap.TryResolveType(cppField.Type, out var typeInfo)) { if (typeInfo.IsFunction) { return(FieldDeclaration( VariableDeclaration(IdentifierName(nameof(IntPtr))) .AddVariables(VariableDeclarator(cppField.Name))) .AddModifiers(Token(SyntaxKind.PublicKeyword)) .AddManagedTypeAttribute(typeInfo.TypeSyntax)); } return(FieldDeclaration( VariableDeclaration(typeInfo.TypeSyntax) .AddVariables(VariableDeclarator(cppField.Name))) .AddModifiers(Token(SyntaxKind.PublicKeyword))); } if (Debugger.IsAttached) { Debugger.Break(); } throw new NotImplementedException(); }
private IEnumerable <StatementSyntax> BuildBaseMethodBody(CppFunction cppFunction, TypeInfo returnTypeInfo) { yield return(SyntaxBuilder.DeclareLocals(false)); var functionPointer = IdentifierName(GetManagedName(cppFunction.Name + "Ptr")); yield return(SyntaxBuilder.CallGuard(functionPointer)); IdentifierNameSyntax result = null; if (!returnTypeInfo.IsVoid) { if (returnTypeInfo.IsFunction) { yield return(SyntaxBuilder.DeclareResultVariable(SyntaxBuilder.IntPtrName, out result)); } else { yield return(SyntaxBuilder.DeclareResultVariable(returnTypeInfo.TypeSyntax, out result)); } } var delegates = new Dictionary <string, string>(); foreach (var cppParameter in cppFunction.Parameters) { if (TypeMap.TryResolveType(cppParameter.Type, out var typeInfo) && typeInfo.IsFunction) { delegates.Add(cppParameter.Name, null); } yield return(SyntaxBuilder.EmitPush(IdentifierName(GetManagedName(cppParameter.Name)))); } yield return(SyntaxBuilder.EmitPush(functionPointer)); yield return(SyntaxBuilder.EmitCalli(returnTypeInfo, cppFunction, TypeMap, delegates)); if (result != null) { yield return(SyntaxBuilder.EmitPop(result)); if (returnTypeInfo.IsFunction) { yield return(ReturnStatement( InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName(nameof(Marshal)), GenericName(nameof(Marshal.GetDelegateForFunctionPointer)) .AddTypeArgumentListArguments(returnTypeInfo.TypeSyntax))) .AddArgumentListArguments(Argument(result)))); } else { yield return(ReturnStatement(result)); } } }
private IEnumerable <MemberDeclarationSyntax> BuildFunctions(CppFunction cppFunction) { Log.WriteLine($"Building function '{GetManagedName(cppFunction.Name)}' from '{cppFunction.Name}'.", ConsoleColor.DarkGray); if (!TypeMap.TryResolveType(cppFunction.ReturnType, out var returnTypeInfo)) { throw new ArgumentException(); } MethodDeclarationSyntax method; if (HasFunctionParameters(cppFunction)) { method = MethodDeclaration(returnTypeInfo.TypeSyntax, GetManagedName(cppFunction.Name) + "Private") .AddModifiers(Token(SyntaxKind.PrivateKeyword), Token(SyntaxKind.StaticKeyword)) .AddParameterListParameters(cppFunction.Parameters.Select(p => BuildParameter(p, false, true)).ToArray()) .AddAggressiveInlining() .WithBody(Block(BuildBaseMethodBody(cppFunction, returnTypeInfo))) .AddUnsafeIfNeeded(); yield return(method); method = MethodDeclaration(returnTypeInfo.TypeSyntax, GetManagedName(cppFunction.Name)) .AddModifiers(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword)) .AddParameterListParameters(cppFunction.Parameters.Select(p => BuildParameter(p, false)).ToArray()) .AddAggressiveInlining() .WithBody(Block(BuildDelegateBody(cppFunction, returnTypeInfo))) .AddUnsafeIfNeeded(); } else { method = MethodDeclaration(returnTypeInfo.TypeSyntax, GetManagedName(cppFunction.Name)) .AddModifiers(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword)) .AddParameterListParameters(cppFunction.Parameters.Select(p => BuildParameter(p, false)).ToArray()) .AddAggressiveInlining() .WithBody(Block(BuildBaseMethodBody(cppFunction, returnTypeInfo))) .AddUnsafeIfNeeded(); } method = method.AddDocumentationComments(cppFunction.Comment, cppFunction.Name); yield return(method); if (cppFunction.Parameters.Any(p => p.Type.IsConstCharPtr())) { method = MethodDeclaration(returnTypeInfo.TypeSyntax, GetManagedName(cppFunction.Name)) .AddModifiers(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword), Token(SyntaxKind.UnsafeKeyword)) .AddParameterListParameters(cppFunction.Parameters.Select(p => BuildParameter(p, true)).ToArray()) .AddAggressiveInlining() .WithBody(Block(BuildStringBody(cppFunction, returnTypeInfo))); method = method.AddDocumentationComments(cppFunction.Comment, cppFunction.Name); yield return(method); } Log.WriteLine("Done.", ConsoleColor.DarkGreen); }
private bool HasFunctionParameters(CppFunction cppFunction) { foreach (var cppParameter in cppFunction.Parameters) { if (TypeMap.TryResolveType(cppParameter.Type, out var typeInfo) && typeInfo.IsFunction) { return(true); } } return(false); }
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 ParameterSyntax BuildParameter(CppParameter cppParameter) { var name = Identifier(cppParameter.Name); if (TypeMap.TryResolveType(cppParameter.Type, out var typeInfo)) { return(Parameter(name).WithType(typeInfo.TypeSyntax)); } if (Debugger.IsAttached) { Debugger.Break(); } throw new NotSupportedException(); }
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))); } }