protected override ExpressionSyntax Generate(CsCallable callable, PlatformDetectionType platform) { var interopSig = callable.InteropSignatures[platform]; var interopReturnType = interopSig.ReturnTypeSyntax; var arguments = IterateNativeArguments(callable is CsMethod, interopSig).ToArray(); var vtblAccess = callable switch { CsMethod method => ElementAccessExpression( ThisExpression(), BracketedArgumentList( SingletonSeparatedList( Argument( method.CustomVtbl ? MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, ThisExpression(), IdentifierName($"{callable.Name}__vtbl_index") ) : method.VTableOffsetExpression(platform) ) ) ) ), _ => null }; ExpressionSyntax FnPtrCall() { var fnptrParameters = arguments .Select(x => x.Type) .Append(interopReturnType) .Select(FunctionPointerParameter); return(GeneratorHelpers.CastExpression( FunctionPointerType( FunctionPointerCallingConvention( Token(SyntaxKind.UnmanagedKeyword), FunctionPointerUnmanagedCallingConventionList( SingletonSeparatedList( FunctionPointerUnmanagedCallingConvention( Identifier(callable.CppCallingConvention.ToCallConvShortName()) ) ) ) ), FunctionPointerParameterList(SeparatedList(fnptrParameters)) ), vtblAccess )); } var what = callable switch { CsFunction => IdentifierName( callable.CppElementName + GeneratorHelpers.GetPlatformSpecificSuffix(platform) ), CsMethod => GeneratorHelpers.WrapInParentheses(FnPtrCall()), _ => throw new ArgumentOutOfRangeException() }; ExpressionSyntax call = InvocationExpression( what, ArgumentList(SeparatedList(arguments.Select(x => x.Argument))) ); if (interopSig.ForcedReturnBufferSig || !callable.HasReturnType) { return(call); } var generatesMarshalVariable = GetMarshaller(callable.ReturnValue).GeneratesMarshalVariable(callable.ReturnValue); var publicTypeSyntax = ReverseCallablePrologCodeGenerator.GetPublicType(callable.ReturnValue); if (callable.HasReturnTypeValue && !generatesMarshalVariable && !publicTypeSyntax.IsEquivalentTo(interopSig.ReturnTypeSyntax)) { call = CastExpression(publicTypeSyntax, call); } return(AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, generatesMarshalVariable ? MarshallerBase.GetMarshalStorageLocation(callable.ReturnValue) : IdentifierName(callable.ReturnValue.Name), call )); }