@@ -161,6 +161,91 @@ internal static ParameterSyntax GetTrampolineInvokeParameter (string trampolineN
161161 . NormalizeWhitespace ( ) ;
162162 }
163163
164+ /// <summary>
165+ ///
166+ /// </summary>
167+ /// <param name="typeInfo"></param>
168+ /// <returns></returns>
169+ internal static TypeSyntax GetLowLevelType ( in TypeInfo typeInfo )
170+ {
171+ #pragma warning disable format
172+ return typeInfo switch {
173+ // pointer parameter
174+ { IsPointer : true } => typeInfo . GetIdentifierSyntax ( ) ,
175+
176+ // delegate parameter is a NativeHandle
177+ { IsDelegate : true } => IntPtr ,
178+
179+ // native enum, return the conversion expression to the native type
180+ { IsNativeEnum : true } => IdentifierName ( typeInfo . EnumUnderlyingType ! . Value . GetKeyword ( ) ) ,
181+
182+ // boolean, convert it to byte
183+ { SpecialType : SpecialType . System_Boolean } => PredefinedType ( Token ( SyntaxKind . ByteKeyword ) ) ,
184+
185+ { IsArray : true } => NativeHandle ,
186+
187+ { SpecialType : SpecialType . System_String } => NativeHandle ,
188+
189+ { IsProtocol : true } => NativeHandle ,
190+
191+ // special types
192+
193+ // CoreMedia.CMSampleBuffer
194+ { FullyQualifiedName : "CoreMedia.CMSampleBuffer" } => NativeHandle ,
195+
196+ // AudioToolbox.AudioBuffers
197+ { FullyQualifiedName : "AudioToolbox.AudioBuffers" } => NativeHandle ,
198+
199+ // general NSObject/INativeObject, has to be after the special types otherwise the special types will
200+ // fall into the NSObject/INativeObject case
201+
202+ // same name, native handle
203+ { IsNSObject : true } => NativeHandle ,
204+
205+ // same name, native handle
206+ { IsINativeObject : true } => NativeHandle ,
207+
208+ // by default, we will use the parameter name as is and the type of the parameter
209+ _ => typeInfo . GetIdentifierSyntax ( ) ,
210+ } ;
211+ #pragma warning restore format
212+ }
213+
214+ /// <summary>
215+ /// Returns the needed data to build the parameter syntax for the native trampoline delegate.
216+ /// </summary>
217+ /// <param name="parameter">The parameter we want to generate for the lower invoke method.</param>
218+ /// <returns>The parameter syntax needed for the parameter.</returns>
219+ internal static ParameterSyntax GetTrampolineInvokeParameter ( in DelegateParameter parameter )
220+ {
221+ // in the general case we will return the low level type conversion of the parameter type but we
222+ // need to handle in a special case those parameters that are passed by reference
223+ var parameterIdentifier = Identifier ( parameter . Name ) ;
224+ #pragma warning disable format
225+ ( SyntaxToken ParameterName , TypeSyntax ParameterType ) parameterInfo = parameter switch {
226+ // parameters that are passed by reference, depend on the type that is referenced
227+ { IsByRef : true , Type . IsReferenceType : false , Type . IsNullable : true }
228+ => ( parameterIdentifier ,
229+ PointerType ( IdentifierName ( parameter . Type . FullyQualifiedName ) ) ) ,
230+
231+ { IsByRef : true , Type . SpecialType : SpecialType . System_Boolean }
232+ => ( parameterIdentifier ,
233+ PointerType ( PredefinedType ( Token ( SyntaxKind . ByteKeyword ) ) ) ) ,
234+
235+ { IsByRef : true , Type . IsReferenceType : true , Type . IsNullable : false }
236+ => ( parameterIdentifier ,
237+ PointerType ( NativeHandle ) ) ,
238+
239+ // by default, we will use the parameter name as is and the type of the parameter
240+ _ => ( parameterIdentifier , GetLowLevelType ( parameter . Type ) ) ,
241+ } ;
242+ #pragma warning restore format
243+
244+ return Parameter ( parameterInfo . ParameterName )
245+ . WithType ( parameterInfo . ParameterType )
246+ . NormalizeWhitespace ( ) ;
247+ }
248+
164249 /// <summary>
165250 /// Returns the argument syntax of a parameter to be used for the trampoliner to invoke a delegate.
166251 /// </summary>
@@ -533,4 +618,43 @@ internal static StatementSyntax CallTrampolineDelegate (in DelegateInfo delegate
533618 EqualsValueClause ( invocation . WithLeadingTrivia ( Space ) ) . WithLeadingTrivia ( Space ) ) ) ) ;
534619 return LocalDeclarationStatement ( declaration ) ;
535620 }
621+
622+ /// <summary>
623+ /// Return the delegate declaration for the trampoline delegate. The trampoline delegate is a delegate that
624+ /// takes as a first parameter a IntPtr that represents the block to be called. The rest of the parameters are
625+ /// the same as the original delegate.
626+ /// </summary>
627+ /// <param name="delegateTypeInfo">The delegate type information.</param>
628+ /// <param name="delegateName">The name of the delegate generated.</param>
629+ /// <returns>The syntax of the delegate.</returns>
630+ internal static SyntaxNode GetTrampolineDelegateDeclaration ( in TypeInfo delegateTypeInfo , out string delegateName )
631+ {
632+ // generate a new delegate type with the addition of the IntPtr parameter for block
633+ var modifiers = TokenList ( Token ( SyntaxKind . UnsafeKeyword ) , Token ( SyntaxKind . InternalKeyword ) ) ;
634+ delegateName = Nomenclator . GetTrampolineClassName ( delegateTypeInfo . Name , Nomenclator . TrampolineClassType . DelegateType ) ;
635+
636+ // build the arguments for the delegate, but add a IntPtr parameter at the start of the list
637+ var parameterBucket = ImmutableArray . CreateBuilder < ParameterSyntax > ( delegateTypeInfo . Delegate ! . Parameters . Length + 1 ) ;
638+ // block parameter needed for the trampoline
639+ parameterBucket . Add (
640+ Parameter ( Identifier ( Nomenclator . GetTrampolineBlockParameterName ( ) ) )
641+ . WithType ( IntPtr ) ) ;
642+ // calculate the rest of the parameters
643+ foreach ( var parameterInfo in delegateTypeInfo . Delegate ! . Parameters ) {
644+ // build the parameter
645+ parameterBucket . Add ( GetTrampolineInvokeParameter ( parameterInfo ) ) ;
646+ }
647+
648+ var parametersSyntax = ParameterList (
649+ SeparatedList < ParameterSyntax > (
650+ parameterBucket . ToImmutableArray ( ) . ToSyntaxNodeOrTokenArray ( ) ) ) . NormalizeWhitespace ( ) ;
651+ // delegate declaration
652+ var declaration = DelegateDeclaration (
653+ GetLowLevelType ( delegateTypeInfo . Delegate ! . ReturnType ) , // return the low level type, not the manged version
654+ Identifier ( delegateName ) )
655+ . WithModifiers ( modifiers ) . NormalizeWhitespace ( )
656+ . WithParameterList ( parametersSyntax . WithLeadingTrivia ( Space ) ) ;
657+
658+ return declaration ;
659+ }
536660}
0 commit comments