@@ -161,6 +161,91 @@ internal static ParameterSyntax GetTrampolineInvokeParameter (string trampolineN
161
161
. NormalizeWhitespace ( ) ;
162
162
}
163
163
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
+
164
249
/// <summary>
165
250
/// Returns the argument syntax of a parameter to be used for the trampoliner to invoke a delegate.
166
251
/// </summary>
@@ -533,4 +618,43 @@ internal static StatementSyntax CallTrampolineDelegate (in DelegateInfo delegate
533
618
EqualsValueClause ( invocation . WithLeadingTrivia ( Space ) ) . WithLeadingTrivia ( Space ) ) ) ) ;
534
619
return LocalDeclarationStatement ( declaration ) ;
535
620
}
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
+ }
536
660
}
0 commit comments