public IEnumerable <StatementSyntax> GenerateSetupStatements(TypePositionInfo info, StubCodeContext context) { yield return(MarshallerHelpers.Declare( _marshallerTypeSyntax, context.GetAdditionalIdentifier(info, MarshallerIdentifier), ImplicitObjectCreationExpression(ArgumentList(), initializer: null))); }
public IEnumerable <StatementSyntax> GenerateSetupStatements(TypePositionInfo info, StubCodeContext context) { // <marshaller> = new(); LocalDeclarationStatementSyntax declaration = MarshallerHelpers.Declare( _marshallerType.Syntax, context.GetAdditionalIdentifier(info, MarshallerIdentifier), ImplicitObjectCreationExpression(ArgumentList(), initializer: null)); // For byref-like marshaller types, we'll mark them as scoped. // Byref-like types can capture references, so by default the compiler has to worry that // they could enable those references to escape the current stack frame. // In particular, this can interact poorly with the caller-allocated-buffer marshalling // support and make the simple `marshaller.FromManaged(managed, stackalloc X[i])` expression // illegal. Mark the marshaller type as scoped so the compiler knows that it won't escape. if (_marshallerType is ValueTypeInfo { IsByRefLike : true })
/// <summary> /// Generate the method body of the p/invoke stub. /// </summary> /// <param name="dllImportName">Name of the target DllImport function to invoke</param> /// <returns>Method body of the p/invoke stub</returns> /// <remarks> /// The generated code assumes it will be in an unsafe context. /// </remarks> public BlockSyntax GeneratePInvokeBody(string dllImportName) { GeneratedStatements statements = GeneratedStatements.Create(_marshallers, _context, IdentifierName(dllImportName)); bool shouldInitializeVariables = !statements.GuaranteedUnmarshal.IsEmpty || !statements.Cleanup.IsEmpty; VariableDeclarations declarations = VariableDeclarations.GenerateDeclarationsForManagedToNative(_marshallers, _context, shouldInitializeVariables); var setupStatements = new List <StatementSyntax>(); if (_setLastError) { // Declare variable for last error setupStatements.Add(MarshallerHelpers.Declare( PredefinedType(Token(SyntaxKind.IntKeyword)), LastErrorIdentifier, initializeToDefault: false)); } if (!statements.GuaranteedUnmarshal.IsEmpty) { setupStatements.Add(MarshallerHelpers.Declare(PredefinedType(Token(SyntaxKind.BoolKeyword)), InvokeSucceededIdentifier, initializeToDefault: true)); } setupStatements.AddRange(declarations.Initializations); setupStatements.AddRange(declarations.Variables); setupStatements.AddRange(statements.Setup); var tryStatements = new List <StatementSyntax>(); tryStatements.AddRange(statements.Marshal); BlockSyntax fixedBlock = Block(statements.PinnedMarshal); if (_setLastError) { StatementSyntax clearLastError = MarshallerHelpers.CreateClearLastSystemErrorStatement(SuccessErrorCode); StatementSyntax getLastError = MarshallerHelpers.CreateGetLastSystemErrorStatement(LastErrorIdentifier); fixedBlock = fixedBlock.AddStatements(clearLastError, statements.InvokeStatement, getLastError); } else { fixedBlock = fixedBlock.AddStatements(statements.InvokeStatement); } tryStatements.Add(statements.Pin.NestFixedStatements(fixedBlock)); // <invokeSucceeded> = true; if (!statements.GuaranteedUnmarshal.IsEmpty) { tryStatements.Add(ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, IdentifierName(InvokeSucceededIdentifier), LiteralExpression(SyntaxKind.TrueLiteralExpression)))); } tryStatements.AddRange(statements.NotifyForSuccessfulInvoke); tryStatements.AddRange(statements.Unmarshal); List <StatementSyntax> allStatements = setupStatements; List <StatementSyntax> finallyStatements = new List <StatementSyntax>(); if (!statements.GuaranteedUnmarshal.IsEmpty) { finallyStatements.Add(IfStatement(IdentifierName(InvokeSucceededIdentifier), Block(statements.GuaranteedUnmarshal))); } finallyStatements.AddRange(statements.Cleanup); if (finallyStatements.Count > 0) { // Add try-finally block if there are any statements in the finally block allStatements.Add( TryStatement(Block(tryStatements), default, FinallyClause(Block(finallyStatements))));