private IEnumerable <StatementSyntax> GenerateNativeByRefProlog(CsMarshalCallableBase publicElement, ExpressionSyntax nativeParameter) { var marshaller = generators.Marshalling.GetMarshaller(publicElement); var localByRef = publicElement.IsRef || publicElement.IsOut; ExpressionSyntax refToNativeExpression = InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, globalNamespace.GetTypeNameSyntax(BuiltinType.Unsafe), GenericName(Identifier("AsRef")) .WithTypeArgumentList( TypeArgumentList( SingletonSeparatedList( marshaller.GetMarshalTypeSyntax(publicElement)))))) .WithArgumentList( ArgumentList( SingletonSeparatedList( Argument( nativeParameter)))); var publicType = ParseTypeName(publicElement.PublicType.QualifiedName); if (localByRef) { if (!marshaller.GeneratesMarshalVariable(publicElement)) { publicType = RefType(publicType); } refToNativeExpression = RefExpression(refToNativeExpression); } if (marshaller.GeneratesMarshalVariable(publicElement)) { yield return(LocalDeclarationStatement( VariableDeclaration( RefType(marshaller.GetMarshalTypeSyntax(publicElement))) .WithVariables( SingletonSeparatedList( VariableDeclarator( generators.Marshalling.GetMarshalStorageLocationIdentifier(publicElement)) .WithInitializer( EqualsValueClause( refToNativeExpression)))))); yield return(LocalDeclarationStatement( VariableDeclaration(publicType) .WithVariables( SingletonSeparatedList( VariableDeclarator( Identifier(publicElement.Name)))))); } else { yield return(LocalDeclarationStatement( VariableDeclaration(publicType) .AddVariables( VariableDeclarator(Identifier(publicElement.Name)) .WithInitializer(EqualsValueClause(refToNativeExpression))))); } }
private static StatementSyntax PlatformSpecificStatement(GlobalNamespaceProvider globalNamespace, PlatformDetectionType allPlatformBitmap, PlatformDetectionType platform, StatementSyntax statement) { if ((platform & allPlatformBitmap) == allPlatformBitmap) { return(statement); } ExpressionSyntax condition = null; foreach (PlatformDetectionType flag in platforms) { if ((platform & flag) == flag && flag != PlatformDetectionType.Any) { var newCondition = MemberAccessExpression( Microsoft.CodeAnalysis.CSharp.SyntaxKind.SimpleMemberAccessExpression, globalNamespace.GetTypeNameSyntax(WellKnownName.PlatformDetection), IdentifierName(flag.ToString())); condition = condition is null ? (ExpressionSyntax)newCondition : BinaryExpression(Microsoft.CodeAnalysis.CSharp.SyntaxKind.LogicalAndExpression, condition, newCondition); } } return(condition is null ? statement : IfStatement( condition, statement)); }
public MemberDeclarationSyntax GenerateCode(CsInterface csElement) { var shadowClassName = csElement.ShadowName.Split('.').Last(); return(ClassDeclaration(shadowClassName) .WithBaseList( BaseList( SingletonSeparatedList <BaseTypeSyntax>( SimpleBaseType( csElement.Base != null ? (NameSyntax)IdentifierName(csElement.Base.ShadowName) : globalNamespace.GetTypeNameSyntax(WellKnownName.CppObjectShadow))))) .WithMembers( List( new MemberDeclarationSyntax[] { generators.Vtbl.GenerateCode(csElement), PropertyDeclaration( globalNamespace.GetTypeNameSyntax(WellKnownName.CppObjectVtbl), Identifier("Vtbl")) .WithModifiers( TokenList( new [] { Token(SyntaxKind.ProtectedKeyword), Token(SyntaxKind.OverrideKeyword) })) .WithAccessorList( AccessorList( SingletonList( AccessorDeclaration( SyntaxKind.GetAccessorDeclaration) .WithSemicolonToken( Token(SyntaxKind.SemicolonToken))))) .WithInitializer( EqualsValueClause( ObjectCreationExpression( IdentifierName(csElement.VtblName)) .WithArgumentList( ArgumentList( SingletonSeparatedList( Argument( LiteralExpression( SyntaxKind.NumericLiteralExpression, Literal(0)))))))) .WithSemicolonToken( Token(SyntaxKind.SemicolonToken)) }))); }
protected ExpressionStatementSyntax GenerateCopyMemoryInvocation(ExpressionSyntax numBytesExpression) { return(ExpressionStatement( InvocationExpression( MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, globalNamespace.GetTypeNameSyntax(WellKnownName.MemoryHelpers), IdentifierName("CopyMemory")), ArgumentList( SeparatedList( new[] { Argument(CastExpression(ParseTypeName("System.IntPtr"), IdentifierName("__to"))), Argument(CastExpression(ParseTypeName("System.IntPtr"), IdentifierName("__from"))), Argument(numBytesExpression) } ))))); }
public static StatementSyntax GetPlatformSpecificStatements(GlobalNamespaceProvider globalNamespace, GeneratorConfig config, IEnumerable <PlatformDetectionType> types, Func <PlatformDetectionType, StatementSyntax> syntaxBuilder) { List <IfStatementSyntax> ifStatements = new(); var allPlatformBitmap = config.Platforms; foreach (var platform in types) { var platformStatement = syntaxBuilder(platform); if ((platform & allPlatformBitmap) == allPlatformBitmap) { return(platformStatement); } ExpressionSyntax condition = null; foreach (var flag in PlatformsNoAny) { if ((platform & flag) != flag) { continue; } var newCondition = MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, globalNamespace.GetTypeNameSyntax(WellKnownName.PlatformDetection), IdentifierName("Is" + flag) ); condition = condition is null ? newCondition : BinaryExpression(SyntaxKind.LogicalAndExpression, condition, newCondition); } ifStatements.Add( condition is null ? (IfStatementSyntax)platformStatement : IfStatement(condition, platformStatement) ); } IfStatementSyntax platformDetectionIfStatement = null; for (var i = ifStatements.Count - 1; i >= 0; i--) { platformDetectionIfStatement = ifStatements[i].WithElse( platformDetectionIfStatement is null ? ElseClause(ThrowPlatformNotSupportedStatement) : ElseClause(platformDetectionIfStatement) ); } return(platformDetectionIfStatement); }
public StatementSyntax GenerateNativeCleanup(CsMarshalBase csElement, bool singleStackFrame) { if (!csElement.IsWideChar || !singleStackFrame) { return(ExpressionStatement( InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, GlobalNamespaceProvider.GetTypeNameSyntax(BuiltinType.Marshal), IdentifierName("FreeHGlobal")), ArgumentList( SingletonSeparatedList( Argument(GetMarshalStorageLocation(csElement))))))); } return(null); }
public StatementSyntax GenerateManagedToNative(CsMarshalBase csElement, bool singleStackFrame) { if (csElement.IsArray) // Fixed-length character array { if (!csElement.IsWideChar) { return(GenerateAnsiStringToArray(csElement)); } if (!singleStackFrame) { return(GenerateStringToArray(csElement)); } return(null); } // Variable-length string represented as a pointer. if (!csElement.IsWideChar || !singleStackFrame) { return(ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, GetMarshalStorageLocation(csElement), InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, GlobalNamespaceProvider.GetTypeNameSyntax(BuiltinType.Marshal), IdentifierName( csElement.IsWideChar ? nameof(Marshal.StringToHGlobalUni) : nameof(Marshal.StringToHGlobalAnsi) ) ), ArgumentList(SingletonSeparatedList(Argument(IdentifierName(csElement.Name)))) ) ) )); } return(null); }
public MemberDeclarationSyntax GenerateCode(CsInterface csElement) { var shadowClassName = csElement.ShadowName.Split('.').Last(); var vtblName = IdentifierName(csElement.VtblName); var vtblConstructor = ArgumentList( SingletonSeparatedList( Argument( LiteralExpression( SyntaxKind.NumericLiteralExpression, Literal(0) ) ) ) ); var vtblProperty = PropertyDeclaration( globalNamespace.GetTypeNameSyntax(WellKnownName.CppObjectVtbl), Identifier("Vtbl") ) .WithModifiers( TokenList(Token(SyntaxKind.ProtectedKeyword), Token(SyntaxKind.OverrideKeyword)) ) .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)); List <MemberDeclarationSyntax> members = new(); if (csElement.AutoGenerateVtbl) { members.Add(generators.Vtbl.GenerateCode(csElement)); } if (csElement.StaticShadowVtbl) { var vtblInstanceName = Identifier("VtblInstance"); members.Add( FieldDeclaration( VariableDeclaration(vtblName) .WithVariables( SingletonSeparatedList( VariableDeclarator(vtblInstanceName) .WithInitializer( EqualsValueClause( ImplicitObjectCreationExpression() .WithArgumentList( vtblConstructor ) ) ) ) ) ) .WithModifiers( TokenList(Token(SyntaxKind.PrivateKeyword), Token(SyntaxKind.StaticKeyword), Token(SyntaxKind.ReadOnlyKeyword)) ) ); vtblProperty = vtblProperty .WithExpressionBody( ArrowExpressionClause(IdentifierName(vtblInstanceName)) ); } else { vtblProperty = vtblProperty .WithAccessorList( AccessorList( SingletonList( AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) ) ) ) .WithInitializer( EqualsValueClause( ObjectCreationExpression(vtblName) .WithArgumentList( vtblConstructor ) ) ); } members.Add(vtblProperty); return(ClassDeclaration(shadowClassName) .WithModifiers( ModelUtilities.VisibilityToTokenList(csElement.ShadowVisibility, SyntaxKind.PartialKeyword) ) .WithBaseList( BaseList( SingletonSeparatedList <BaseTypeSyntax>( SimpleBaseType( csElement.Base != null ? IdentifierName(csElement.Base.ShadowName) : globalNamespace.GetTypeNameSyntax(WellKnownName.CppObjectShadow) ) ) ) ) .WithMembers(new SyntaxList <MemberDeclarationSyntax>(members))); }
public MemberDeclarationSyntax GenerateCode(CsInterface csElement) { var vtblClassName = csElement.VtblName.Split('.').Last(); return(ClassDeclaration(vtblClassName) .WithModifiers( TokenList( Token(SyntaxKind.ProtectedKeyword), Token(SyntaxKind.UnsafeKeyword))) .WithBaseList( BaseList( SingletonSeparatedList <BaseTypeSyntax>( SimpleBaseType( csElement.Base != null ? (NameSyntax)IdentifierName(csElement.Base.VtblName) : globalNamespace.GetTypeNameSyntax(WellKnownName.CppObjectVtbl))))) .WithMembers( List( new MemberDeclarationSyntax[] { ConstructorDeclaration( Identifier(vtblClassName)) .WithModifiers( TokenList( Token(SyntaxKind.PublicKeyword))) .WithParameterList( ParameterList( SingletonSeparatedList( Parameter( Identifier("numberOfCallbackMethods")) .WithType( PredefinedType( Token(SyntaxKind.IntKeyword)))))) .WithInitializer( ConstructorInitializer( SyntaxKind.BaseConstructorInitializer, ArgumentList( SingletonSeparatedList( Argument( BinaryExpression( SyntaxKind.AddExpression, IdentifierName("numberOfCallbackMethods"), LiteralExpression( SyntaxKind.NumericLiteralExpression, Literal(csElement.Methods.Count())))))))) .WithBody( Block(csElement.Methods .OrderBy(method => method.Offset) .Select(method => ExpressionStatement( InvocationExpression( IdentifierName("AddMethod")) .WithArgumentList( ArgumentList( SingletonSeparatedList( Argument( ObjectCreationExpression( IdentifierName($"{method.Name}Delegate")) .WithArgumentList( ArgumentList( SingletonSeparatedList( Argument( IdentifierName(method.Name))))))))))))) } .Concat(csElement.Methods .SelectMany(method => generators.ShadowCallable.GenerateCode(method)))))); }
private StatementSyntax GenerateStringToArray(CsMarshalBase marshallable) { var lengthIdentifier = LengthIdentifier(marshallable); return(FixedStatement( VariableDeclaration( PointerType(PredefinedType(Token(SyntaxKind.CharKeyword))), SeparatedList( new[] { VariableDeclarator(FromIdentifier) .WithInitializer(EqualsValueClause(IdentifierName(marshallable.Name))), VariableDeclarator(ToIdentifier) .WithInitializer(EqualsValueClause( PrefixUnaryExpression(SyntaxKind.AddressOfExpression, GetMarshalStorageLocation(marshallable)))) }) ), Block( LocalDeclarationStatement( VariableDeclaration( PredefinedType(Token(SyntaxKind.IntKeyword)), SingletonSeparatedList( VariableDeclarator(Identifier(lengthIdentifier)) .WithInitializer(EqualsValueClause( InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, GlobalNamespaceProvider.GetTypeNameSyntax(BuiltinType.Math), IdentifierName(nameof(Math.Min))), ArgumentList( SeparatedList( new[] { Argument( BinaryExpression(SyntaxKind.MultiplyExpression, ParenthesizedExpression( BinaryExpression(SyntaxKind.CoalesceExpression, ConditionalAccessExpression( IdentifierName(marshallable.Name), MemberBindingExpression(IdentifierName("Length"))), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(0)))), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(2)) )), Argument( BinaryExpression(SyntaxKind.MultiplyExpression, LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(marshallable.ArrayDimensionValue - 1)), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(2)))) } ) ))))))), GenerateCopyMemoryInvocation(IdentifierName(lengthIdentifier)), ExpressionStatement( AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, ElementAccessExpression(IdentifierName(ToIdentifier), BracketedArgumentList( SingletonSeparatedList( Argument(IdentifierName(lengthIdentifier))))), LiteralExpression(SyntaxKind.CharacterLiteralExpression, Literal('\0'))))))); }
public StatementSyntax GenerateNativeToManaged(CsMarshalBase csElement, bool singleStackFrame) { MemberAccessExpressionSyntax PtrToString(NameSyntax implName) => MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, implName, IdentifierName( csElement.IsWideChar ? nameof(Marshal.PtrToStringUni) : nameof(Marshal.PtrToStringAnsi) ) ); if (csElement.IsArray) // Fixed-length character array { if (csElement.IsWideChar && singleStackFrame) { return(null); } const string ptrName = "__ptr"; return(FixedStatement( VariableDeclaration( VoidPtrType, SingletonSeparatedList( VariableDeclarator(ptrName) .WithInitializer( EqualsValueClause( PrefixUnaryExpression( SyntaxKind.AddressOfExpression, GetMarshalStorageLocation(csElement) ) ) ) ) ), ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, IdentifierName(csElement.Name), InvocationExpression( PtrToString(GlobalNamespace.GetTypeNameSyntax(WellKnownName.StringHelpers)), ArgumentList( SeparatedList( new[] { Argument(CastExpression(IntPtrType, IdentifierName(ptrName))), Argument( LiteralExpression( SyntaxKind.NumericLiteralExpression, Literal(csElement.ArrayDimensionValue - 1) ) ) } ) ) ) ) ) )); } // Variable-length string represented as a pointer. return(ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, IdentifierName(csElement.Name), InvocationExpression( PtrToString(GlobalNamespaceProvider.GetTypeNameSyntax(BuiltinType.Marshal)), ArgumentList(SingletonSeparatedList(Argument(GetMarshalStorageLocation(csElement)))) ) ) )); }
private StatementSyntax GenerateAnsiStringToArray(CsMarshalBase marshallable) { return(Block( LocalDeclarationStatement( VariableDeclaration( PredefinedType(Token(SyntaxKind.IntKeyword)), SingletonSeparatedList( VariableDeclarator(Identifier($"{marshallable.Name}_length")) .WithInitializer(EqualsValueClause( InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, GlobalNamespaceProvider.GetTypeNameSyntax(BuiltinType.Math), IdentifierName("Min")), ArgumentList( SeparatedList( new[] { Argument( BinaryExpression(SyntaxKind.CoalesceExpression, ConditionalAccessExpression( IdentifierName(marshallable.Name), MemberBindingExpression(IdentifierName("Length"))), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(0)))), Argument( LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(marshallable.ArrayDimensionValue - 1))) } ) ))))))), LocalDeclarationStatement( VariableDeclaration( ParseTypeName("System.IntPtr"), SingletonSeparatedList( VariableDeclarator(Identifier("__from")) .WithInitializer(EqualsValueClause( InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, GlobalNamespaceProvider.GetTypeNameSyntax(BuiltinType.Marshal), IdentifierName("StringToHGlobalAnsi"))) .WithArgumentList( ArgumentList(SingletonSeparatedList(Argument(IdentifierName(marshallable.Name)))))))))), FixedStatement( VariableDeclaration( PointerType(PredefinedType(Token(SyntaxKind.ByteKeyword))), SingletonSeparatedList( VariableDeclarator("__to") .WithInitializer(EqualsValueClause( PrefixUnaryExpression(SyntaxKind.AddressOfExpression, GetMarshalStorageLocation(marshallable))))) ), Block( GenerateCopyMemoryInvocation(IdentifierName($"{marshallable.Name}_length")), ExpressionStatement( AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, ElementAccessExpression(IdentifierName("__to"), BracketedArgumentList( SingletonSeparatedList( Argument(IdentifierName($"{marshallable.Name}_length"))))), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(0)))))), ExpressionStatement(InvocationExpression( MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, GlobalNamespaceProvider.GetTypeNameSyntax(BuiltinType.Marshal), IdentifierName("FreeHGlobal")), ArgumentList(SingletonSeparatedList( Argument(IdentifierName($"__from")))))) )); }
public StatementSyntax GenerateNativeToManaged(CsMarshalBase csElement, bool singleStackFrame) { if (csElement.IsArray) // Fixed-length character array { if (!csElement.IsWideChar || !singleStackFrame) { return(FixedStatement( VariableDeclaration(PointerType(PredefinedType(Token(SyntaxKind.VoidKeyword))), SingletonSeparatedList( VariableDeclarator("__ptr") .WithInitializer(EqualsValueClause( PrefixUnaryExpression(SyntaxKind.AddressOfExpression, GetMarshalStorageLocation(csElement)) )))), ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, IdentifierName(csElement.Name), InvocationExpression( MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, globalNamespace.GetTypeNameSyntax(WellKnownName.StringHelpers), IdentifierName("PtrToString" + (csElement.IsWideChar ? "Uni" : "Ansi"))), ArgumentList(SeparatedList( new[] { Argument(CastExpression(ParseTypeName("System.IntPtr"), IdentifierName("__ptr"))), Argument(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(csElement.ArrayDimensionValue - 1))) } ))))))); } return(null); } if (!csElement.IsWideChar || !singleStackFrame) // Variable-length string represented as a pointer. { return(ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, IdentifierName(csElement.Name), InvocationExpression( MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, GlobalNamespaceProvider.GetTypeNameSyntax(BuiltinType.Marshal), IdentifierName("PtrToString" + (csElement.IsWideChar ? "Uni" : "Ansi"))), ArgumentList(SingletonSeparatedList( Argument( GetMarshalStorageLocation(csElement)))))))); } return(null); }
public ExpressionSyntax GenerateCall(CsCallable callable, PlatformDetectionType platform, InteropMethodSignature interopSig) { var arguments = IterateNativeArguments(callable, interopSig).ToArray(); ElementAccessExpressionSyntax vtblAccess = null; if (callable is CsMethod method) { var windowsOffsetExpression = LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(method.WindowsOffset)); var nonWindowsOffsetExpression = LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(method.Offset)); ExpressionSyntax vtableOffsetExpression; if ((platform & PlatformDetectionType.Any) == PlatformDetectionType.Any && method.Offset != method.WindowsOffset) { vtableOffsetExpression = ConditionalExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, globalNamespace.GetTypeNameSyntax(WellKnownName.PlatformDetection), IdentifierName("Is" + nameof(PlatformDetectionType.Windows))), windowsOffsetExpression, nonWindowsOffsetExpression); } else if ((platform & PlatformDetectionType.Windows) != 0) { vtableOffsetExpression = windowsOffsetExpression; } else { vtableOffsetExpression = nonWindowsOffsetExpression; } vtblAccess = ElementAccessExpression( ParenthesizedExpression( PrefixUnaryExpression( SyntaxKind.PointerIndirectionExpression, CastExpression( TripleVoidPtr, MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, ThisExpression(), IdentifierName("_nativePointer") ) ) ) ), BracketedArgumentList( SingletonSeparatedList( Argument( method.CustomVtbl ? MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, ThisExpression(), IdentifierName($"{callable.Name}__vtbl_index") ) : vtableOffsetExpression ) ) ) ); } CastExpressionSyntax FnPtrCall() { var fnptrParameters = arguments .Select(x => x.Type) .Append(ParseTypeName(interopSig.ReturnType.TypeName)) .Select(FunctionPointerParameter); return(CastExpression( FunctionPointerType( FunctionPointerCallingConvention( Token(SyntaxKind.UnmanagedKeyword), FunctionPointerUnmanagedCallingConventionList( SingletonSeparatedList( FunctionPointerUnmanagedCallingConvention( Identifier(callable.CppCallingConvention.ToCallConvShortName()) ) ) ) ), FunctionPointerParameterList(SeparatedList(fnptrParameters)) ), ParenthesizedExpression(vtblAccess) )); } ExpressionSyntax what = callable switch { CsFunction => IdentifierName( callable.CppElementName + GeneratorHelpers.GetPlatformSpecificSuffix(platform) ), CsMethod => ParenthesizedExpression(FnPtrCall()), _ => throw new ArgumentOutOfRangeException() }; ExpressionSyntax call = InvocationExpression( what, ArgumentList(SeparatedList(arguments.Select(x => x.Argument))) ); if (interopSig.CastToNativeLong) { call = CastExpression(globalNamespace.GetTypeNameSyntax(WellKnownName.NativeLong), call); } if (interopSig.CastToNativeULong) { call = CastExpression(globalNamespace.GetTypeNameSyntax(WellKnownName.NativeULong), call); } if (interopSig.ForcedReturnBufferSig || !callable.HasReturnType) { return(call); } var generatesMarshalVariable = generators.Marshalling .GetMarshaller(callable.ReturnValue) .GeneratesMarshalVariable(callable.ReturnValue); return(AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, generatesMarshalVariable ? MarshallerBase.GetMarshalStorageLocation(callable.ReturnValue) : IdentifierName(callable.ReturnValue.Name), call )); } }
public MemberDeclarationSyntax GenerateCode(CsInterface csElement) { var vtblClassName = csElement.VtblName.Split('.').Last(); // Default: at least protected to enable inheritance. var vtblVisibility = csElement.VtblVisibility ?? Visibility.ProtectedInternal; StatementSyntax VtblMethodSelector(CsMethod method) { StatementSyntax MethodBuilder(PlatformDetectionType platform) { var arguments = new[] { Argument( ObjectCreationExpression(IdentifierName(GetMethodDelegateName(method, platform))) .WithArgumentList( ArgumentList( SingletonSeparatedList( Argument( IdentifierName( $"{method.Name}{GeneratorHelpers.GetPlatformSpecificSuffix(platform)}" ) ) ) ) ) ), Argument( LiteralExpression( SyntaxKind.NumericLiteralExpression, Literal((platform & PlatformDetectionType.Windows) != 0 ? method.WindowsOffset : method.Offset) ) ) }; return(ExpressionStatement( InvocationExpression(IdentifierName("AddMethod")) .WithArgumentList(ArgumentList(SeparatedList(arguments))) )); } return(GeneratorHelpers.GetPlatformSpecificStatements(globalNamespace, generators.Config, method.InteropSignatures.Keys, MethodBuilder)); } List <MemberDeclarationSyntax> members = new() { ConstructorDeclaration(Identifier(vtblClassName)) .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))) .WithParameterList( ParameterList( SingletonSeparatedList( Parameter(Identifier("numberOfCallbackMethods")) .WithType(PredefinedType(Token(SyntaxKind.IntKeyword))) ) ) ) .WithInitializer( ConstructorInitializer( SyntaxKind.BaseConstructorInitializer, ArgumentList( SingletonSeparatedList( Argument( BinaryExpression( SyntaxKind.AddExpression, IdentifierName("numberOfCallbackMethods"), LiteralExpression( SyntaxKind.NumericLiteralExpression, Literal(csElement.MethodList.Count) ) ) ) ) ) ) ) .WithBody( Block( csElement.Methods .OrderBy(method => method.Offset) .Select(VtblMethodSelector) ) ) }; members.AddRange(csElement.Methods.SelectMany(method => generators.ShadowCallable.GenerateCode(method))); return(ClassDeclaration(vtblClassName) .WithModifiers( ModelUtilities.VisibilityToTokenList(vtblVisibility, SyntaxKind.UnsafeKeyword, SyntaxKind.PartialKeyword) ) .WithBaseList( BaseList( SingletonSeparatedList <BaseTypeSyntax>( SimpleBaseType( csElement.Base != null ? IdentifierName(csElement.Base.VtblName) : globalNamespace.GetTypeNameSyntax(WellKnownName.CppObjectVtbl) ) ) ) ) .WithMembers(List(members))); }
private StatementSyntax GenerateCopyBlock(CsMarshalBase parameter, CopyBlockDirection direction) { var arrayIdentifier = IdentifierName(parameter.Name); var pointerIdentifier = GetMarshalStorageLocationIdentifier(parameter); var fixedName = $"{pointerIdentifier}_"; var fixedInitializer = VariableDeclarator(fixedName) .WithInitializer(EqualsValueClause(arrayIdentifier)); var unsafeName = GlobalNamespaceProvider.GetTypeNameSyntax(BuiltinType.Unsafe); var destination = direction switch { CopyBlockDirection.UnmanagedToFixedArray => Identifier(fixedName), CopyBlockDirection.FixedArrayToUnmanaged => pointerIdentifier, _ => throw new ArgumentOutOfRangeException(nameof(direction)) }; var source = direction switch { CopyBlockDirection.UnmanagedToFixedArray => pointerIdentifier, CopyBlockDirection.FixedArrayToUnmanaged => Identifier(fixedName), _ => throw new ArgumentOutOfRangeException(nameof(direction)) }; var invokeArguments = ArgumentList( SeparatedList( new[] { Argument(IdentifierName(destination)), Argument(IdentifierName(source)), Argument( CastExpression( PredefinedType(Token(SyntaxKind.UIntKeyword)), ParenthesizedExpression( BinaryExpression( SyntaxKind.MultiplyExpression, MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, arrayIdentifier, IdentifierName("Length") ), InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, unsafeName, GenericName( Identifier(nameof(Unsafe.SizeOf)), TypeArgumentList( SingletonSeparatedList <TypeSyntax>( IdentifierName(parameter.PublicType.QualifiedName) ) ) ) ) ) ) ) ) ) } ) ); return(FixedStatement( VariableDeclaration( VoidPtrType, SingletonSeparatedList(fixedInitializer) ), ExpressionStatement( InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, unsafeName, IdentifierName(nameof(Unsafe.CopyBlockUnaligned)) ), invokeArguments ) ) )); } } }