diff --git a/src/rgen/Microsoft.Macios.Generator/Emitters/BindingSyntaxFactory.KnownTypes.cs b/src/rgen/Microsoft.Macios.Generator/Emitters/BindingSyntaxFactory.KnownTypes.cs
index 47c7b440f53..091a7fad7de 100644
--- a/src/rgen/Microsoft.Macios.Generator/Emitters/BindingSyntaxFactory.KnownTypes.cs
+++ b/src/rgen/Microsoft.Macios.Generator/Emitters/BindingSyntaxFactory.KnownTypes.cs
@@ -68,6 +68,13 @@ static partial class BindingSyntaxFactory {
@namespace: ["ObjCRuntime"],
@class: "Runtime");
+ ///
+ /// TypeSyntax for ObjCRuntime.BlockLiteral.
+ ///
+ public static readonly TypeSyntax BlockLiteral = StringExtensions.GetIdentifierName (
+ @namespace: ["ObjCRuntime"],
+ @class: "BlockLiteral");
+
// Foundation types
///
diff --git a/src/rgen/Microsoft.Macios.Generator/Emitters/Documentation.cs b/src/rgen/Microsoft.Macios.Generator/Emitters/Documentation.cs
index 9025697643e..d2a1c6028bb 100644
--- a/src/rgen/Microsoft.Macios.Generator/Emitters/Documentation.cs
+++ b/src/rgen/Microsoft.Macios.Generator/Emitters/Documentation.cs
@@ -135,5 +135,8 @@ public static string DefaultInitWithHandle (string name) =>
/// Developers should not invoke this method directly, instead they should call as it will prevent two instances of a managed object pointing to the same native object.
///
/// ";
+
+ public static string TrampolineStaticClass (string name) =>
+"/// This class bridges native block invocations that call into C# ";
}
}
diff --git a/src/rgen/Microsoft.Macios.Generator/Emitters/TrampolineEmitter.cs b/src/rgen/Microsoft.Macios.Generator/Emitters/TrampolineEmitter.cs
index 1f06e97b9be..9479f5d0811 100644
--- a/src/rgen/Microsoft.Macios.Generator/Emitters/TrampolineEmitter.cs
+++ b/src/rgen/Microsoft.Macios.Generator/Emitters/TrampolineEmitter.cs
@@ -3,21 +3,164 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
+using System.IO;
+using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.Macios.Generator.Context;
-using Microsoft.Macios.Generator.DataModel;
+using Microsoft.Macios.Generator.Formatters;
using Microsoft.Macios.Generator.IO;
using TypeInfo = Microsoft.Macios.Generator.DataModel.TypeInfo;
+using static Microsoft.Macios.Generator.Emitters.BindingSyntaxFactory;
namespace Microsoft.Macios.Generator.Emitters;
class TrampolineEmitter (
RootContext context,
TabbedStringBuilder builder) {
+ ///
+ /// The nomenclator is used to generate the name of the static class that will contain the trampoline, needs to
+ /// be an instance class since we want to keep track of the already generated names.
+ ///
+ Nomenclator nomenclator = new ();
public string SymbolNamespace => "ObjCRuntime";
public string SymbolName => "Trampolines";
+ ///
+ /// Generate the static helper class for the trampoline uses to bridge the native block invocation.
+ ///
+ /// The type info of the trampoline to generate.
+ /// The trampoline name.
+ /// The tabbed string builder to use.
+ /// True if the code was generated, false otherwise.
+ public bool TryEmitStaticClass (in TypeInfo typeInfo, string trampolineName, TabbedWriter classBuilder)
+ {
+ // create a new static class using the name from the nomenclator
+ var argumentSyntax = GetTrampolineInvokeArguments (trampolineName, typeInfo.Delegate!);
+ var delegateIdentifier = typeInfo.GetIdentifierSyntax ();
+ var className = Nomenclator.GetTrampolineClassName (trampolineName, Nomenclator.TrampolineClassType.StaticBridgeClass);
+ var invokeMethodName = Nomenclator.GetTrampolineInvokeMethodName ();
+ var trampolineVariableName = Nomenclator.GetTrampolineDelegatePointerVariableName ();
+ var delegateVariableName = Nomenclator.GetTrampolineDelegateVariableName ();
+
+ classBuilder.WriteDocumentation (Documentation.Class.TrampolineStaticClass (className));
+ using (var classBlock = classBuilder.CreateBlock ($"static internal class {className}", true)) {
+ // Invoke method
+ classBlock.WriteLine ("[Preserve (Conditional = true)]");
+ classBlock.WriteLine ("[UnmanagedCallersOnly]");
+ classBlock.WriteLine ($"[UserDelegateType (typeof ({delegateIdentifier}))]");
+ using (var invokeMethod = classBlock.CreateBlock (GetTrampolineInvokeSignature (typeInfo).ToString (), true)) {
+ // initialized the parameters, this might be needed for the parameters that are out or ref
+ foreach (var argument in argumentSyntax) {
+ invokeMethod.Write (argument.Initializers);
+ }
+
+ // get the delegate from the block literal to execute with the trampoline
+ invokeMethod.WriteLine ($"var {delegateVariableName} = {BlockLiteral}.GetTarget<{delegateIdentifier}> ({Nomenclator.GetTrampolineBlockParameterName (typeInfo.Delegate!.Parameters)});");
+
+ // if the deletate is null, we return default, otherwise we call the delegate
+ using (var ifBlock = invokeMethod.CreateBlock ($"if ({delegateVariableName} is not null)", true)) {
+
+ // build any needed pre conversion operations before calling the delegate
+ foreach (var argument in argumentSyntax) {
+ ifBlock.Write (argument.PreDelegateCallConversion);
+ }
+
+ ifBlock.WriteLine ($"{CallTrampolineDelegate (typeInfo.Delegate!, argumentSyntax)}");
+
+ // build any needed post conversion operations after calling the delegate
+ foreach (var argument in argumentSyntax) {
+ ifBlock.Write (argument.PostDelegateCallConversion);
+ }
+
+ // perform any needed
+ if (typeInfo.Delegate.ReturnType.SpecialType != SpecialType.System_Void)
+ ifBlock.WriteLine ($"return {GetTrampolineInvokeReturnType (typeInfo, Nomenclator.GetReturnVariableName ())};");
+ }
+ if (typeInfo.Delegate.ReturnType.SpecialType != SpecialType.System_Void)
+ invokeMethod.WriteLine ("return default;");
+ }
+
+ // CreateNullableBlock
+ classBlock.WriteLine (); // empty line for readability
+ using (var createNullableBlock = classBlock.CreateBlock (
+ $"internal static unsafe {BlockLiteral} CreateNullableBlock ({delegateIdentifier}? callback)", true)) {
+ createNullableBlock.WriteRaw (
+$@"if (callback is null)
+ return default ({BlockLiteral});
+return CreateBlock (callback);
+"
+ );
+ }
+
+ // CreateBlock
+ classBlock.WriteLine (); // empty line for readability
+ classBlock.WriteLine ("[BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]");
+ using (var createBlock = classBlock.CreateBlock (
+ $"internal static unsafe {BlockLiteral} CreateBlock ({delegateIdentifier} callback)", true)) {
+ createBlock.WriteLine (GetTrampolineDelegatePointer (typeInfo).ToFullString ());
+ createBlock.WriteLine (
+ $"return new {BlockLiteral} ({trampolineVariableName}, callback, typeof ({className}), nameof ({invokeMethodName}));");
+ }
+ }
+ return true;
+ }
+
+ ///
+ /// Emits the delegate declaration for the trampoline.
+ ///
+ /// The type of the trampoline to generate.
+ /// The current tabbed string builder to use.
+ /// A hash set with the delegates already added.
+ /// The delegate name.
+ /// True if the code was generated, false otherwise.
+ public bool TryEmitInternalDelegate (in TypeInfo typeInfo, TabbedWriter classBuilder, HashSet addedDelegates,
+ [NotNullWhen (true)] out string? delegateName)
+ {
+ delegateName = null;
+ if (typeInfo.Delegate is null)
+ return false;
+
+ // generate the delegate and get its name, if we already emitted it, skip it
+ var delegateDeclaration = GetTrampolineDelegateDeclaration (typeInfo, out delegateName);
+ if (addedDelegates.Add (delegateName)) {
+ // print the attributes needed for the delegate and the delegate itself
+ classBuilder.WriteLine ("[UnmanagedFunctionPointerAttribute (CallingConvention.Cdecl)]");
+ classBuilder.WriteLine ($"[UserDelegateType (typeof ({typeInfo.GetIdentifierSyntax ()}))]");
+ classBuilder.WriteLine (delegateDeclaration.ToString ());
+ }
+ return true;
+ }
+
+ ///
+ /// Write the using statements for the namespaces used by the trampolines.
+ ///
+ /// The trampolines to generate.
+ public void WriteUsedNamespaces (IReadOnlySet trampolines)
+ {
+ // create set with the default namespaces
+ var namespaces = new HashSet () {
+ "Foundation",
+ "ObjCBindings",
+ "ObjCRuntime",
+ "System",
+ };
+ // loop through the trampolines and add the namespaces used by the delegates
+ foreach (var info in trampolines)
+ namespaces.Add (string.Join ('.', info.Namespace));
+
+ // sort the namespaces so that we can write them in a deterministic way
+ foreach (var ns in namespaces.OrderBy (x => x)) {
+ builder.WriteLine ($"using {ns};");
+ }
+ }
+
+ ///
+ /// Generate the trampolines for the given set of types.
+ ///
+ /// The trampolines type info to use for the code generation.
+ /// Possible diagnostic errors.
+ /// True if the code was generated, false otherwise.
public bool TryEmit (IReadOnlySet trampolines,
[NotNullWhen (false)] out ImmutableArray? diagnostics)
{
@@ -25,19 +168,35 @@ public bool TryEmit (IReadOnlySet trampolines,
// and some comments with the trampolines to emit
diagnostics = null;
- builder.WriteLine ("using Foundation;");
- builder.WriteLine ("using ObjCBindings;");
- builder.WriteLine ("using ObjCRuntime;");
- builder.WriteLine ("using System;");
+ // write the using statements
+ WriteUsedNamespaces (trampolines);
builder.WriteLine ();
- builder.WriteLine ($"namespace ObjCRuntime;");
+ builder.WriteLine ("namespace ObjCRuntime;");
builder.WriteLine ();
+ // keep track of the already emitted delegates
+ var addedDelegates = new HashSet ();
+
using (var classBlock = builder.CreateBlock ($"static partial class {SymbolName}", true)) {
classBlock.WriteLine ($"// Generate trampolines for compilation");
_ = context.CurrentPlatform;
foreach (var info in trampolines) {
+ var trampolineName = nomenclator.GetTrampolineName (info);
+ // write the delegate declaration
+ if (!TryEmitInternalDelegate (info, classBlock, addedDelegates, out var delegateDeclaration)) {
+ diagnostics = [];
+ return false;
+ }
+
+ classBlock.WriteLine (); // empty line for readability
+
+ // generate the static class
+ if (!TryEmitStaticClass (info, trampolineName, classBlock)) {
+ diagnostics = [];
+ return false;
+ }
+
classBlock.WriteLine ($"// TODO: generate trampoline for {info.FullyQualifiedName}");
classBlock.WriteLine ();
}
diff --git a/tests/rgen/Microsoft.Macios.Generator.Tests/BaseGeneratorTestClass.cs b/tests/rgen/Microsoft.Macios.Generator.Tests/BaseGeneratorTestClass.cs
index 959b1f4fdfe..ddb73fcbd32 100644
--- a/tests/rgen/Microsoft.Macios.Generator.Tests/BaseGeneratorTestClass.cs
+++ b/tests/rgen/Microsoft.Macios.Generator.Tests/BaseGeneratorTestClass.cs
@@ -122,7 +122,7 @@ protected void CompareGeneratedCode (GenerationTestData testData)
if (testData.ExpectedTrampolineText is not null) {
// validate that Library.g.cs was created by the LibraryEmitter and matches the expectation
- var generatedLibSyntax = runResult.GeneratedTrees.Single (t => t.FilePath.EndsWith ("Trampolines.g.cs"));
+ var generatedLibSyntax = runResult.GeneratedTrees.Single (t => t.FilePath.EndsWith ("ObjCRuntime/Trampolines.g.cs"));
Assert.Equal (testData.ExpectedTrampolineText, generatedLibSyntax.GetText ().ToString ());
}
}
diff --git a/tests/rgen/Microsoft.Macios.Generator.Tests/Classes/ClassGenerationTests.cs b/tests/rgen/Microsoft.Macios.Generator.Tests/Classes/ClassGenerationTests.cs
index f56062e4641..ea365e9dfb7 100644
--- a/tests/rgen/Microsoft.Macios.Generator.Tests/Classes/ClassGenerationTests.cs
+++ b/tests/rgen/Microsoft.Macios.Generator.Tests/Classes/ClassGenerationTests.cs
@@ -47,6 +47,9 @@ public class TestDataGenerator : BaseTestDataGenerator, IEnumerable {
(ApplePlatform.TVOS, "TrampolinePropertyTests", "TrampolinePropertyTests.cs", "ExpectedTrampolinePropertyTests.cs", null, "ExpectedTrampolinePropertyTestsTrampolines.cs"),
(ApplePlatform.MacCatalyst, "TrampolinePropertyTests", "TrampolinePropertyTests.cs", "ExpectedTrampolinePropertyTests.cs", null, "ExpectedTrampolinePropertyTestsTrampolines.cs"),
(ApplePlatform.MacOSX, "TrampolinePropertyTests", "TrampolinePropertyTests.cs", "ExpectedTrampolinePropertyTests.cs", null, "ExpectedTrampolinePropertyTestsTrampolines.cs"),
+
+ // ARKit trampoline tests, only present on iOS
+ (ApplePlatform.iOS, "ARKitTrampolines", "Trampolines/ARKitTrampolines.cs", "Trampolines/ExpectedARKitTrampolinesProperties.cs", null, "Trampolines/ExpectedARKitTrampolinesTrampolines.cs"),
};
public IEnumerator GetEnumerator ()
diff --git a/tests/rgen/Microsoft.Macios.Generator.Tests/Classes/Data/ExpectedTrampolinePropertyTests.cs b/tests/rgen/Microsoft.Macios.Generator.Tests/Classes/Data/ExpectedTrampolinePropertyTests.cs
index 34e68a97680..525223609d4 100644
--- a/tests/rgen/Microsoft.Macios.Generator.Tests/Classes/Data/ExpectedTrampolinePropertyTests.cs
+++ b/tests/rgen/Microsoft.Macios.Generator.Tests/Classes/Data/ExpectedTrampolinePropertyTests.cs
@@ -2,7 +2,9 @@
#nullable enable
+using AVFoundation;
using CoreGraphics;
+using CoreImage;
using Foundation;
using ObjCBindings;
using ObjCRuntime;
@@ -20,6 +22,14 @@ namespace Microsoft.Macios.Generator.Tests.Classes.Data.TestNamespace;
[Register ("TrampolinePropertyTests", true)]
public partial class TrampolinePropertyTests
{
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ const string selCreateObjectHandlerX = "createObjectHandler";
+ static readonly global::ObjCRuntime.NativeHandle selCreateObjectHandlerXHandle = global::ObjCRuntime.Selector.GetHandle ("createObjectHandler");
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ const string selSetCreateObjectHandler_X = "setCreateObjectHandler:";
+ static readonly global::ObjCRuntime.NativeHandle selSetCreateObjectHandler_XHandle = global::ObjCRuntime.Selector.GetHandle ("setCreateObjectHandler:");
+
[BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
const string selCompletionHandlerX = "completionHandler";
static readonly global::ObjCRuntime.NativeHandle selCompletionHandlerXHandle = global::ObjCRuntime.Selector.GetHandle ("completionHandler");
@@ -28,6 +38,62 @@ public partial class TrampolinePropertyTests
const string selSetCompletionHandler_X = "setCompletionHandler:";
static readonly global::ObjCRuntime.NativeHandle selSetCompletionHandler_XHandle = global::ObjCRuntime.Selector.GetHandle ("setCompletionHandler:");
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ const string selDuplicateCompletionHandlerX = "duplicateCompletionHandler";
+ static readonly global::ObjCRuntime.NativeHandle selDuplicateCompletionHandlerXHandle = global::ObjCRuntime.Selector.GetHandle ("duplicateCompletionHandler");
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ const string selSetDuplicateCompletionHandler_X = "setDuplicateCompletionHandler:";
+ static readonly global::ObjCRuntime.NativeHandle selSetDuplicateCompletionHandler_XHandle = global::ObjCRuntime.Selector.GetHandle ("setDuplicateCompletionHandler:");
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ const string selImageGeneratorCompletionHandlerX = "imageGeneratorCompletionHandler";
+ static readonly global::ObjCRuntime.NativeHandle selImageGeneratorCompletionHandlerXHandle = global::ObjCRuntime.Selector.GetHandle ("imageGeneratorCompletionHandler");
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ const string selSetImageGeneratorCompletionHandler_X = "setImageGeneratorCompletionHandler:";
+ static readonly global::ObjCRuntime.NativeHandle selSetImageGeneratorCompletionHandler_XHandle = global::ObjCRuntime.Selector.GetHandle ("setImageGeneratorCompletionHandler:");
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ const string selKernelRoiCallbackX = "kernelRoiCallback";
+ static readonly global::ObjCRuntime.NativeHandle selKernelRoiCallbackXHandle = global::ObjCRuntime.Selector.GetHandle ("kernelRoiCallback");
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ const string selSetKernelRoiCallback_X = "setKernelRoiCallback:";
+ static readonly global::ObjCRuntime.NativeHandle selSetKernelRoiCallback_XHandle = global::ObjCRuntime.Selector.GetHandle ("setKernelRoiCallback:");
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ const string selStringActionHandlerX = "stringActionHandler";
+ static readonly global::ObjCRuntime.NativeHandle selStringActionHandlerXHandle = global::ObjCRuntime.Selector.GetHandle ("stringActionHandler");
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ const string selSetStringActionHandler_X = "setStringActionHandler:";
+ static readonly global::ObjCRuntime.NativeHandle selSetStringActionHandler_XHandle = global::ObjCRuntime.Selector.GetHandle ("setStringActionHandler:");
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ const string selIntActionHandlerX = "intActionHandler";
+ static readonly global::ObjCRuntime.NativeHandle selIntActionHandlerXHandle = global::ObjCRuntime.Selector.GetHandle ("intActionHandler");
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ const string selSetIntActionHandler_X = "setIntActionHandler:";
+ static readonly global::ObjCRuntime.NativeHandle selSetIntActionHandler_XHandle = global::ObjCRuntime.Selector.GetHandle ("setIntActionHandler:");
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ const string selBoolActionHandlerX = "boolActionHandler";
+ static readonly global::ObjCRuntime.NativeHandle selBoolActionHandlerXHandle = global::ObjCRuntime.Selector.GetHandle ("boolActionHandler");
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ const string selSetBoolActionHandler_X = "setBoolActionHandler:";
+ static readonly global::ObjCRuntime.NativeHandle selSetBoolActionHandler_XHandle = global::ObjCRuntime.Selector.GetHandle ("setBoolActionHandler:");
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ const string selManualRenderingCallbackX = "manualRenderingCallback";
+ static readonly global::ObjCRuntime.NativeHandle selManualRenderingCallbackXHandle = global::ObjCRuntime.Selector.GetHandle ("manualRenderingCallback");
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ const string selSetManualRenderingCallback_X = "setManualRenderingCallback:";
+ static readonly global::ObjCRuntime.NativeHandle selSetManualRenderingCallback_XHandle = global::ObjCRuntime.Selector.GetHandle ("setManualRenderingCallback:");
+
[BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
static readonly global::ObjCRuntime.NativeHandle class_ptr = global::ObjCRuntime.Class.GetHandle ("TrampolinePropertyTests");
@@ -113,6 +179,27 @@ protected TrampolinePropertyTests (global::Foundation.NSObjectFlag t) : base (t)
[EditorBrowsable (EditorBrowsableState.Advanced)]
protected internal TrampolinePropertyTests (global::ObjCRuntime.NativeHandle handle) : base (handle) {}
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ public partial global::System.Action BoolActionHandler
+ {
+ get
+ {
+ global::System.Action ret;
+ if (IsDirectBinding) {
+ ret = global::ObjCRuntime.Messaging.NativeHandle_objc_msgSend (this.Handle, global::ObjCRuntime.Selector.GetHandle ("boolActionHandler"));
+ } else {
+ ret = global::ObjCRuntime.Messaging.NativeHandle_objc_msgSendSuper (this.Handle, global::ObjCRuntime.Selector.GetHandle ("boolActionHandler"));
+ }
+ GC.KeepAlive (this);
+ return ret;
+ }
+
+ set
+ {
+ throw new NotImplementedException();
+ }
+ }
+
[BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
public partial global::System.Action CompletionHandler
{
@@ -133,5 +220,194 @@ protected internal TrampolinePropertyTests (global::ObjCRuntime.NativeHandle han
throw new NotImplementedException();
}
}
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ public partial global::Microsoft.Macios.Generator.Tests.Classes.Data.TestNamespace.TrampolinePropertyTests.CreateObject CreateObjectHandler
+ {
+ get
+ {
+ global::Microsoft.Macios.Generator.Tests.Classes.Data.TestNamespace.TrampolinePropertyTests.CreateObject ret;
+ if (IsDirectBinding) {
+ ret = global::ObjCRuntime.Messaging.NativeHandle_objc_msgSend (this.Handle, global::ObjCRuntime.Selector.GetHandle ("createObjectHandler"));
+ } else {
+ ret = global::ObjCRuntime.Messaging.NativeHandle_objc_msgSendSuper (this.Handle, global::ObjCRuntime.Selector.GetHandle ("createObjectHandler"));
+ }
+ GC.KeepAlive (this);
+ return ret;
+ }
+
+ set
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ public partial global::System.Action DuplicateCompletionHandler
+ {
+ get
+ {
+ global::System.Action ret;
+ if (IsDirectBinding) {
+ ret = global::ObjCRuntime.Messaging.NativeHandle_objc_msgSend (this.Handle, global::ObjCRuntime.Selector.GetHandle ("duplicateCompletionHandler"));
+ } else {
+ ret = global::ObjCRuntime.Messaging.NativeHandle_objc_msgSendSuper (this.Handle, global::ObjCRuntime.Selector.GetHandle ("duplicateCompletionHandler"));
+ }
+ GC.KeepAlive (this);
+ return ret;
+ }
+
+ set
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ public partial global::AVFoundation.AVAssetImageGenerator.AsynchronouslyForTimeCompletionHandler ImageGeneratorCompletionHandler
+ {
+ get
+ {
+ global::AVFoundation.AVAssetImageGenerator.AsynchronouslyForTimeCompletionHandler ret;
+ if (IsDirectBinding) {
+ ret = global::ObjCRuntime.Messaging._objc_msgSend (this.Handle, global::ObjCRuntime.Selector.GetHandle ("imageGeneratorCompletionHandler"));
+ } else {
+ ret = global::ObjCRuntime.Messaging._objc_msgSendSuper (this.Handle, global::ObjCRuntime.Selector.GetHandle ("imageGeneratorCompletionHandler"));
+ }
+ GC.KeepAlive (this);
+ return ret;
+ }
+
+ set
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ public partial global::AVFoundation.AVAssetImageGenerateAsynchronouslyForTimeCompletionHandler ImageGeneratorCompletionHandler
+ {
+ get
+ {
+ global::AVFoundation.AVAssetImageGenerateAsynchronouslyForTimeCompletionHandler ret;
+ if (IsDirectBinding) {
+ ret = global::ObjCRuntime.Messaging.NativeHandle_objc_msgSend (this.Handle, global::ObjCRuntime.Selector.GetHandle ("imageGeneratorCompletionHandler"));
+ } else {
+ ret = global::ObjCRuntime.Messaging.NativeHandle_objc_msgSendSuper (this.Handle, global::ObjCRuntime.Selector.GetHandle ("imageGeneratorCompletionHandler"));
+ }
+ GC.KeepAlive (this);
+ return ret;
+ }
+
+ set
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ public partial global::System.Action IntActionHandler
+ {
+ get
+ {
+ global::System.Action ret;
+ if (IsDirectBinding) {
+ ret = global::ObjCRuntime.Messaging.NativeHandle_objc_msgSend (this.Handle, global::ObjCRuntime.Selector.GetHandle ("intActionHandler"));
+ } else {
+ ret = global::ObjCRuntime.Messaging.NativeHandle_objc_msgSendSuper (this.Handle, global::ObjCRuntime.Selector.GetHandle ("intActionHandler"));
+ }
+ GC.KeepAlive (this);
+ return ret;
+ }
+
+ set
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ public partial global::CoreImage.CIKernelRoiCallback KernelRoiCallback
+ {
+ get
+ {
+ global::CoreImage.CIKernelRoiCallback ret;
+ if (IsDirectBinding) {
+ ret = global::ObjCRuntime.Messaging.NativeHandle_objc_msgSend (this.Handle, global::ObjCRuntime.Selector.GetHandle ("kernelRoiCallback"));
+ } else {
+ ret = global::ObjCRuntime.Messaging.NativeHandle_objc_msgSendSuper (this.Handle, global::ObjCRuntime.Selector.GetHandle ("kernelRoiCallback"));
+ }
+ GC.KeepAlive (this);
+ return ret;
+ }
+
+ set
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ public partial global::CoreImage.CIKernelRoiCallback KernelRoiCallback
+ {
+ get
+ {
+ global::CoreImage.CIKernelRoiCallback ret;
+ if (IsDirectBinding) {
+ ret = global::ObjCRuntime.Messaging.NativeHandle_objc_msgSend (this.Handle, global::ObjCRuntime.Selector.GetHandle ("kernelRoiCallback"));
+ } else {
+ ret = global::ObjCRuntime.Messaging.NativeHandle_objc_msgSendSuper (this.Handle, global::ObjCRuntime.Selector.GetHandle ("kernelRoiCallback"));
+ }
+ GC.KeepAlive (this);
+ return ret;
+ }
+
+ set
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ public partial global::AVFoundation.AVAudioEngineManualRenderingBlock ManualRendering
+ {
+ get
+ {
+ global::AVFoundation.AVAudioEngineManualRenderingBlock ret;
+ if (IsDirectBinding) {
+ ret = global::ObjCRuntime.Messaging.NativeHandle_objc_msgSend (this.Handle, global::ObjCRuntime.Selector.GetHandle ("manualRenderingCallback"));
+ } else {
+ ret = global::ObjCRuntime.Messaging.NativeHandle_objc_msgSendSuper (this.Handle, global::ObjCRuntime.Selector.GetHandle ("manualRenderingCallback"));
+ }
+ GC.KeepAlive (this);
+ return ret;
+ }
+
+ set
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ public partial global::System.Action StringActionHandler
+ {
+ get
+ {
+ global::System.Action ret;
+ if (IsDirectBinding) {
+ ret = global::ObjCRuntime.Messaging.NativeHandle_objc_msgSend (this.Handle, global::ObjCRuntime.Selector.GetHandle ("stringActionHandler"));
+ } else {
+ ret = global::ObjCRuntime.Messaging.NativeHandle_objc_msgSendSuper (this.Handle, global::ObjCRuntime.Selector.GetHandle ("stringActionHandler"));
+ }
+ GC.KeepAlive (this);
+ return ret;
+ }
+
+ set
+ {
+ throw new NotImplementedException();
+ }
+ }
// TODO: add binding code here
}
diff --git a/tests/rgen/Microsoft.Macios.Generator.Tests/Classes/Data/ExpectedTrampolinePropertyTestsTrampolines.cs b/tests/rgen/Microsoft.Macios.Generator.Tests/Classes/Data/ExpectedTrampolinePropertyTestsTrampolines.cs
index e6dbd4fde88..fa4919703a9 100644
--- a/tests/rgen/Microsoft.Macios.Generator.Tests/Classes/Data/ExpectedTrampolinePropertyTestsTrampolines.cs
+++ b/tests/rgen/Microsoft.Macios.Generator.Tests/Classes/Data/ExpectedTrampolinePropertyTestsTrampolines.cs
@@ -2,7 +2,10 @@
#nullable enable
+using AVFoundation;
+using CoreImage;
using Foundation;
+using Microsoft.Macios.Generator.Tests.Classes.Data.TestNamespace;
using ObjCBindings;
using ObjCRuntime;
using System;
@@ -12,6 +15,282 @@ namespace ObjCRuntime;
static partial class Trampolines
{
// Generate trampolines for compilation
+ [UnmanagedFunctionPointerAttribute (CallingConvention.Cdecl)]
+ [UserDelegateType (typeof (global::Microsoft.Macios.Generator.Tests.Classes.Data.TestNamespace.TrampolinePropertyTests.CreateObject))]
+ unsafe internal delegate global::ObjCRuntime.NativeHandle DTrampolinePropertyTests.CreateObject (global::System.IntPtr block_ptr, global::ObjCRuntime.NativeHandle obj);
+
+ /// This class bridges native block invocations that call into C#
+ static internal class SDTrampolinePropertyTests.CreateObject
+ {
+ [Preserve (Conditional = true)]
+ [UnmanagedCallersOnly]
+ [UserDelegateType (typeof (global::Microsoft.Macios.Generator.Tests.Classes.Data.TestNamespace.TrampolinePropertyTests.CreateObject))]
+ internal static unsafe global::ObjCRuntime.NativeHandle Invoke (global::System.IntPtr block_ptr, global::ObjCRuntime.NativeHandle obj)
+ {
+ var del = global::ObjCRuntime.BlockLiteral.GetTarget (block_ptr);
+ if (del is not null)
+ {
+ var ret = del (global::ObjCRuntime.Runtime.GetNSObject (obj)!);
+ return global::ObjCRuntime.Runtime.RetainAndAutoreleaseNSObject (ret);
+ }
+ return default;
+ }
+
+ internal static unsafe global::ObjCRuntime.BlockLiteral CreateNullableBlock (global::Microsoft.Macios.Generator.Tests.Classes.Data.TestNamespace.TrampolinePropertyTests.CreateObject? callback)
+ {
+ if (callback is null)
+ return default (global::ObjCRuntime.BlockLiteral);
+ return CreateBlock (callback);
+ }
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ internal static unsafe global::ObjCRuntime.BlockLiteral CreateBlock (global::Microsoft.Macios.Generator.Tests.Classes.Data.TestNamespace.TrampolinePropertyTests.CreateObject callback)
+ {
+ delegate* unmanaged trampoline = &Invoke;
+ return new global::ObjCRuntime.BlockLiteral (trampoline, callback, typeof (SDTrampolinePropertyTests.CreateObject), nameof (Invoke));
+ }
+ }
+ // TODO: generate trampoline for Microsoft.Macios.Generator.Tests.Classes.Data.TestNamespace.TrampolinePropertyTests.CreateObject
+
+ [UnmanagedFunctionPointerAttribute (CallingConvention.Cdecl)]
+ [UserDelegateType (typeof (global::System.Action))]
+ unsafe internal delegate void DAction (global::System.IntPtr block_ptr);
+
+ /// This class bridges native block invocations that call into C#
+ static internal class SDAction
+ {
+ [Preserve (Conditional = true)]
+ [UnmanagedCallersOnly]
+ [UserDelegateType (typeof (global::System.Action))]
+ internal static unsafe void Invoke (global::System.IntPtr block_ptr)
+ {
+ var del = global::ObjCRuntime.BlockLiteral.GetTarget (block_ptr);
+ if (del is not null)
+ {
+ del ();
+ }
+ }
+
+ internal static unsafe global::ObjCRuntime.BlockLiteral CreateNullableBlock (global::System.Action? callback)
+ {
+ if (callback is null)
+ return default (global::ObjCRuntime.BlockLiteral);
+ return CreateBlock (callback);
+ }
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ internal static unsafe global::ObjCRuntime.BlockLiteral CreateBlock (global::System.Action callback)
+ {
+ delegate* unmanaged trampoline = &Invoke;
+ return new global::ObjCRuntime.BlockLiteral (trampoline, callback, typeof (SDAction), nameof (Invoke));
+ }
+ }
// TODO: generate trampoline for System.Action
+ [UnmanagedFunctionPointerAttribute (CallingConvention.Cdecl)]
+ [UserDelegateType (typeof (global::CoreImage.CIKernelRoiCallback))]
+ unsafe internal delegate global::CoreGraphics.CGRect DCIKernelRoiCallback (global::System.IntPtr block_ptr, int index, global::CoreGraphics.CGRect rect);
+
+ /// This class bridges native block invocations that call into C#
+ static internal class SDCIKernelRoiCallback
+ {
+ [Preserve (Conditional = true)]
+ [UnmanagedCallersOnly]
+ [UserDelegateType (typeof (global::CoreImage.CIKernelRoiCallback))]
+ internal static unsafe global::CoreGraphics.CGRect Invoke (global::System.IntPtr block_ptr, int index, global::CoreGraphics.CGRect rect)
+ {
+ var del = global::ObjCRuntime.BlockLiteral.GetTarget (block_ptr);
+ if (del is not null)
+ {
+ var ret = del (index, rect);
+ return ret;
+ }
+ return default;
+ }
+
+ internal static unsafe global::ObjCRuntime.BlockLiteral CreateNullableBlock (global::CoreImage.CIKernelRoiCallback? callback)
+ {
+ if (callback is null)
+ return default (global::ObjCRuntime.BlockLiteral);
+ return CreateBlock (callback);
+ }
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ internal static unsafe global::ObjCRuntime.BlockLiteral CreateBlock (global::CoreImage.CIKernelRoiCallback callback)
+ {
+ delegate* unmanaged trampoline = &Invoke;
+ return new global::ObjCRuntime.BlockLiteral (trampoline, callback, typeof (SDCIKernelRoiCallback), nameof (Invoke));
+ }
+ }
+ // TODO: generate trampoline for CoreImage.CIKernelRoiCallback
+
+
+ /// This class bridges native block invocations that call into C#
+ static internal class SDActionArity1V0
+ {
+ [Preserve (Conditional = true)]
+ [UnmanagedCallersOnly]
+ [UserDelegateType (typeof (global::System.Action))]
+ internal static unsafe void Invoke (global::System.IntPtr block_ptr, global::ObjCRuntime.NativeHandle obj)
+ {
+ var del = global::ObjCRuntime.BlockLiteral.GetTarget> (block_ptr);
+ if (del is not null)
+ {
+ del (global::CoreFoundation.CFString.FromHandle (obj)!);
+ }
+ }
+
+ internal static unsafe global::ObjCRuntime.BlockLiteral CreateNullableBlock (global::System.Action? callback)
+ {
+ if (callback is null)
+ return default (global::ObjCRuntime.BlockLiteral);
+ return CreateBlock (callback);
+ }
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ internal static unsafe global::ObjCRuntime.BlockLiteral CreateBlock (global::System.Action callback)
+ {
+ delegate* unmanaged trampoline = &Invoke;
+ return new global::ObjCRuntime.BlockLiteral (trampoline, callback, typeof (SDActionArity1V0), nameof (Invoke));
+ }
+ }
+ // TODO: generate trampoline for System.Action
+
+
+ /// This class bridges native block invocations that call into C#
+ static internal class SDActionArity1V1
+ {
+ [Preserve (Conditional = true)]
+ [UnmanagedCallersOnly]
+ [UserDelegateType (typeof (global::System.Action))]
+ internal static unsafe void Invoke (global::System.IntPtr block_ptr, int obj)
+ {
+ var del = global::ObjCRuntime.BlockLiteral.GetTarget> (block_ptr);
+ if (del is not null)
+ {
+ del (obj);
+ }
+ }
+
+ internal static unsafe global::ObjCRuntime.BlockLiteral CreateNullableBlock (global::System.Action? callback)
+ {
+ if (callback is null)
+ return default (global::ObjCRuntime.BlockLiteral);
+ return CreateBlock (callback);
+ }
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ internal static unsafe global::ObjCRuntime.BlockLiteral CreateBlock (global::System.Action callback)
+ {
+ delegate* unmanaged trampoline = &Invoke;
+ return new global::ObjCRuntime.BlockLiteral (trampoline, callback, typeof (SDActionArity1V1), nameof (Invoke));
+ }
+ }
+ // TODO: generate trampoline for System.Action
+
+
+ /// This class bridges native block invocations that call into C#
+ static internal class SDActionArity1V2
+ {
+ [Preserve (Conditional = true)]
+ [UnmanagedCallersOnly]
+ [UserDelegateType (typeof (global::System.Action))]
+ internal static unsafe void Invoke (global::System.IntPtr block_ptr, byte obj)
+ {
+ var del = global::ObjCRuntime.BlockLiteral.GetTarget> (block_ptr);
+ if (del is not null)
+ {
+ del (obj != 0);
+ }
+ }
+
+ internal static unsafe global::ObjCRuntime.BlockLiteral CreateNullableBlock (global::System.Action? callback)
+ {
+ if (callback is null)
+ return default (global::ObjCRuntime.BlockLiteral);
+ return CreateBlock (callback);
+ }
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ internal static unsafe global::ObjCRuntime.BlockLiteral CreateBlock (global::System.Action callback)
+ {
+ delegate* unmanaged trampoline = &Invoke;
+ return new global::ObjCRuntime.BlockLiteral (trampoline, callback, typeof (SDActionArity1V2), nameof (Invoke));
+ }
+ }
+ // TODO: generate trampoline for System.Action
+
+ [UnmanagedFunctionPointerAttribute (CallingConvention.Cdecl)]
+ [UserDelegateType (typeof (global::AVFoundation.AVAssetImageGenerateAsynchronouslyForTimeCompletionHandler))]
+ unsafe internal delegate void DAVAssetImageGenerateAsynchronouslyForTimeCompletionHandler (global::System.IntPtr block_ptr, global::ObjCRuntime.NativeHandle imageRef, global::CoreMedia.CMTime actualTime, global::ObjCRuntime.NativeHandle error);
+
+ /// This class bridges native block invocations that call into C#
+ static internal class SDAVAssetImageGenerateAsynchronouslyForTimeCompletionHandler
+ {
+ [Preserve (Conditional = true)]
+ [UnmanagedCallersOnly]
+ [UserDelegateType (typeof (global::AVFoundation.AVAssetImageGenerateAsynchronouslyForTimeCompletionHandler))]
+ internal static unsafe void Invoke (global::System.IntPtr block_ptr, global::ObjCRuntime.NativeHandle imageRef, global::CoreMedia.CMTime actualTime, global::ObjCRuntime.NativeHandle error)
+ {
+ var del = global::ObjCRuntime.BlockLiteral.GetTarget (block_ptr);
+ if (del is not null)
+ {
+ del (global::ObjCRuntime.Runtime.GetINativeObject (imageRef, false)!, actualTime, global::ObjCRuntime.Runtime.GetNSObject (error)!);
+ }
+ }
+
+ internal static unsafe global::ObjCRuntime.BlockLiteral CreateNullableBlock (global::AVFoundation.AVAssetImageGenerateAsynchronouslyForTimeCompletionHandler? callback)
+ {
+ if (callback is null)
+ return default (global::ObjCRuntime.BlockLiteral);
+ return CreateBlock (callback);
+ }
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ internal static unsafe global::ObjCRuntime.BlockLiteral CreateBlock (global::AVFoundation.AVAssetImageGenerateAsynchronouslyForTimeCompletionHandler callback)
+ {
+ delegate* unmanaged trampoline = &Invoke;
+ return new global::ObjCRuntime.BlockLiteral (trampoline, callback, typeof (SDAVAssetImageGenerateAsynchronouslyForTimeCompletionHandler), nameof (Invoke));
+ }
+ }
+ // TODO: generate trampoline for AVFoundation.AVAssetImageGenerateAsynchronouslyForTimeCompletionHandler
+
+ [UnmanagedFunctionPointerAttribute (CallingConvention.Cdecl)]
+ [UserDelegateType (typeof (global::AVFoundation.AVAudioEngineManualRenderingBlock))]
+ unsafe internal delegate global::System.IntPtr DAVAudioEngineManualRenderingBlock (global::System.IntPtr block_ptr, uint numberOfFrames, global::ObjCRuntime.NativeHandle outBuffer, int* outError);
+
+ /// This class bridges native block invocations that call into C#
+ static internal class SDAVAudioEngineManualRenderingBlock
+ {
+ [Preserve (Conditional = true)]
+ [UnmanagedCallersOnly]
+ [UserDelegateType (typeof (global::AVFoundation.AVAudioEngineManualRenderingBlock))]
+ internal static unsafe global::System.IntPtr Invoke (global::System.IntPtr block_ptr, uint numberOfFrames, global::ObjCRuntime.NativeHandle outBuffer, int* outError)
+ {
+ *outError = default;
+ var del = global::ObjCRuntime.BlockLiteral.GetTarget (block_ptr);
+ if (del is not null)
+ {
+ var ret = del (numberOfFrames, new global::AudioToolbox.AudioBuffers (outBuffer), ref global::System.Runtime.CompilerServices.Unsafe.AsRef (outError));
+ return (IntPtr) (long) ret;
+ }
+ return default;
+ }
+
+ internal static unsafe global::ObjCRuntime.BlockLiteral CreateNullableBlock (global::AVFoundation.AVAudioEngineManualRenderingBlock? callback)
+ {
+ if (callback is null)
+ return default (global::ObjCRuntime.BlockLiteral);
+ return CreateBlock (callback);
+ }
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ internal static unsafe global::ObjCRuntime.BlockLiteral CreateBlock (global::AVFoundation.AVAudioEngineManualRenderingBlock callback)
+ {
+ delegate* unmanaged trampoline = &Invoke;
+ return new global::ObjCRuntime.BlockLiteral (trampoline, callback, typeof (SDAVAudioEngineManualRenderingBlock), nameof (Invoke));
+ }
+ }
+ // TODO: generate trampoline for AVFoundation.AVAudioEngineManualRenderingBlock
+
}
diff --git a/tests/rgen/Microsoft.Macios.Generator.Tests/Classes/Data/TrampolinePropertyTests.cs b/tests/rgen/Microsoft.Macios.Generator.Tests/Classes/Data/TrampolinePropertyTests.cs
index 38701c21642..1cfb989abb2 100644
--- a/tests/rgen/Microsoft.Macios.Generator.Tests/Classes/Data/TrampolinePropertyTests.cs
+++ b/tests/rgen/Microsoft.Macios.Generator.Tests/Classes/Data/TrampolinePropertyTests.cs
@@ -8,6 +8,8 @@ namespace Microsoft.Macios.Generator.Tests.Classes.Data;
using System;
using System.Runtime.Versioning;
+using AVFoundation;
+using CoreImage;
using CoreGraphics;
using Foundation;
using ObjCBindings;
@@ -18,6 +20,46 @@ namespace TestNamespace;
[BindingType]
public partial class TrampolinePropertyTests {
+ public delegate NSObject CreateObject (NSObject obj);
+
+ [Export ("createObjectHandler", ArgumentSemantic.Copy)]
+ public partial CreateObject CreateObjectHandler { get; set; }
+
[Export ("completionHandler", ArgumentSemantic.Copy)]
public partial Action CompletionHandler { get; set; }
+
+ // Duplicate property using Action
+ [Export ("duplicateCompletionHandler", ArgumentSemantic.Copy)]
+ public partial Action DuplicateCompletionHandler { get; set; }
+
+ [Export ("imageGeneratorCompletionHandler", ArgumentSemantic.Copy)]
+ public partial AVAssetImageGenerator.AsynchronouslyForTimeCompletionHandler ImageGeneratorCompletionHandler { get; set; }
+
+ // Property using CIKernelRoiCallback
+ [Export ("kernelRoiCallback", ArgumentSemantic.Copy)]
+ public partial CIKernelRoiCallback KernelRoiCallback { get; set; }]
+
+ // Property using Action
+ [Export ("stringActionHandler", ArgumentSemantic.Copy)]
+ public partial Action StringActionHandler { get; set; }
+
+ // Property using Action
+ [Export ("intActionHandler", ArgumentSemantic.Copy)]
+ public partial Action IntActionHandler { get; set; }
+
+ // Property using Action
+ [Export ("boolActionHandler", ArgumentSemantic.Copy)]
+ public partial Action BoolActionHandler { get; set; }
+
+ // Property using AVAssetImageGenerator.AsynchronouslyForTimeCompletionHandler
+ [Export ("imageGeneratorCompletionHandler", ArgumentSemantic.Copy)]
+ public partial AVAssetImageGenerateAsynchronouslyForTimeCompletionHandler ImageGeneratorCompletionHandler { get; set; }
+
+ // Property using CIKernelRoiCallback
+ [Export ("kernelRoiCallback", ArgumentSemantic.Copy)]
+ public partial CIKernelRoiCallback KernelRoiCallback { get; set; }
+
+ // Property using AVAssetImageGenerator.AsynchronouslyForTimeCompletionHandler
+ [Export ("manualRenderingCallback", ArgumentSemantic.Copy)]
+ public partial AVAudioEngineManualRenderingBlock ManualRendering { get; set; }
}
diff --git a/tests/rgen/Microsoft.Macios.Generator.Tests/Classes/Data/Trampolines/ARKitTrampolines.cs b/tests/rgen/Microsoft.Macios.Generator.Tests/Classes/Data/Trampolines/ARKitTrampolines.cs
new file mode 100644
index 00000000000..31a91a839c9
--- /dev/null
+++ b/tests/rgen/Microsoft.Macios.Generator.Tests/Classes/Data/Trampolines/ARKitTrampolines.cs
@@ -0,0 +1,19 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System;
+using System.Runtime.Versioning;
+using ARKit;
+using Foundation;
+using ObjCBindings;
+using ObjCRuntime;
+
+namespace TestNamespace;
+
+[BindingType]
+public partial class ARKitTrampolines {
+
+ [Export ("geolocationCallbackHandler", ArgumentSemantic.Copy)]
+ public partial ARKit.GetGeolocationCallback GeolocationCallbackHandler { get; set; }
+
+}
diff --git a/tests/rgen/Microsoft.Macios.Generator.Tests/Classes/Data/Trampolines/ExpectedARKitTrampolinesProperties.cs b/tests/rgen/Microsoft.Macios.Generator.Tests/Classes/Data/Trampolines/ExpectedARKitTrampolinesProperties.cs
new file mode 100644
index 00000000000..f3fc9f4ce8d
--- /dev/null
+++ b/tests/rgen/Microsoft.Macios.Generator.Tests/Classes/Data/Trampolines/ExpectedARKitTrampolinesProperties.cs
@@ -0,0 +1,137 @@
+//
+
+#nullable enable
+
+using ARKit;
+using Foundation;
+using ObjCBindings;
+using ObjCRuntime;
+using System;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Drawing;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+using System.Threading.Tasks;
+
+namespace TestNamespace;
+
+[Register ("ARKitTrampolines", true)]
+public partial class ARKitTrampolines
+{
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ const string selGeolocationCallbackHandlerX = "geolocationCallbackHandler";
+ static readonly global::ObjCRuntime.NativeHandle selGeolocationCallbackHandlerXHandle = global::ObjCRuntime.Selector.GetHandle ("geolocationCallbackHandler");
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ const string selSetGeolocationCallbackHandler_X = "setGeolocationCallbackHandler:";
+ static readonly global::ObjCRuntime.NativeHandle selSetGeolocationCallbackHandler_XHandle = global::ObjCRuntime.Selector.GetHandle ("setGeolocationCallbackHandler:");
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ static readonly global::ObjCRuntime.NativeHandle class_ptr = global::ObjCRuntime.Class.GetHandle ("ARKitTrampolines");
+
+ /// The Objective-C class handle for this class.
+ /// The pointer to the Objective-C class.
+ ///
+ /// Each managed class mirrors an unmanaged Objective-C class.
+ /// This value contains the pointer to the Objective-C class.
+ /// It is similar to calling the managed or the native objc_getClass method with the type name.
+ ///
+ public override global::ObjCRuntime.NativeHandle ClassHandle => class_ptr;
+
+ /// Creates a new with default values.
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ [DesignatedInitializer]
+ [Export ("init")]
+ public ARKitTrampolines () : base (global::Foundation.NSObjectFlag.Empty)
+ {
+ if (IsDirectBinding)
+ InitializeHandle (global::ObjCRuntime.Messaging.IntPtr_objc_msgSend (this.Handle, global::ObjCRuntime.Selector.GetHandle ("init")), "init");
+ else
+ InitializeHandle (global::ObjCRuntime.Messaging.IntPtr_objc_msgSendSuper (this.SuperHandle, global::ObjCRuntime.Selector.GetHandle ("init")), "init");
+ }
+
+ /// Constructor to call on derived classes to skip initialization and merely allocate the object.
+ /// Unused sentinel value, pass NSObjectFlag.Empty.
+ ///
+ ///
+ /// This constructor should be called by derived classes when they completely construct the object in managed code and merely want the runtime to allocate and initialize the .
+ /// This is required to implement the two-step initialization process that Objective-C uses, the first step is to perform the object allocation, the second step is to initialize the object.
+ /// When developers invoke this constructor, they take advantage of a direct path that goes all the way up to to merely allocate the object's memory and bind the Objective-C and C# objects together.
+ /// The actual initialization of the object is up to the developer.
+ ///
+ ///
+ /// This constructor is typically used by the binding generator to allocate the object, but prevent the actual initialization to take place.
+ /// Once the allocation has taken place, the constructor has to initialize the object.
+ /// With constructors generated by the binding generator this means that it manually invokes one of the "init" methods to initialize the object.
+ ///
+ /// It is the developer's responsibility to completely initialize the object if they chain up using this constructor chain.
+ ///
+ /// In general, if the developer's constructor invokes the corresponding base implementation, then it should also call an Objective-C init method.
+ /// If this is not the case, developers should instead chain to the proper constructor in their class.
+ ///
+ ///
+ /// The argument value is ignored and merely ensures that the only code that is executed is the construction phase is the basic allocation and runtime type registration.
+ /// Typically the chaining would look like this:
+ ///
+ ///
+ ///
+ ///
+ ///
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ [EditorBrowsable (EditorBrowsableState.Advanced)]
+ protected ARKitTrampolines (global::Foundation.NSObjectFlag t) : base (t) {}
+
+ /// A constructor used when creating managed representations of unmanaged objects. Called by the runtime.
+ /// Pointer (handle) to the unmanaged object.
+ ///
+ ///
+ /// This constructor is invoked by the runtime infrastructure ( ) to create a new managed representation for a pointer to an unmanaged Objective-C object.
+ /// Developers should not invoke this method directly, instead they should call as it will prevent two instances of a managed object pointing to the same native object.
+ ///
+ ///
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ [EditorBrowsable (EditorBrowsableState.Advanced)]
+ protected internal ARKitTrampolines (global::ObjCRuntime.NativeHandle handle) : base (handle) {}
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ public partial global::ARKit.GetGeolocationCallback GeolocationCallbackHandler
+ {
+ get
+ {
+ global::ARKit.GetGeolocationCallback ret;
+ if (IsDirectBinding) {
+ ret = global::ObjCRuntime.Messaging.NativeHandle_objc_msgSend (this.Handle, global::ObjCRuntime.Selector.GetHandle ("geolocationCallbackHandler"));
+ } else {
+ ret = global::ObjCRuntime.Messaging.NativeHandle_objc_msgSendSuper (this.Handle, global::ObjCRuntime.Selector.GetHandle ("geolocationCallbackHandler"));
+ }
+ GC.KeepAlive (this);
+ return ret;
+ }
+
+ set
+ {
+ throw new NotImplementedException();
+ }
+ }
+ // TODO: add binding code here
+}
diff --git a/tests/rgen/Microsoft.Macios.Generator.Tests/Classes/Data/Trampolines/ExpectedARKitTrampolinesTrampolines.cs b/tests/rgen/Microsoft.Macios.Generator.Tests/Classes/Data/Trampolines/ExpectedARKitTrampolinesTrampolines.cs
new file mode 100644
index 00000000000..ac81d401251
--- /dev/null
+++ b/tests/rgen/Microsoft.Macios.Generator.Tests/Classes/Data/Trampolines/ExpectedARKitTrampolinesTrampolines.cs
@@ -0,0 +1,51 @@
+//
+
+#nullable enable
+
+using ARKit;
+using Foundation;
+using ObjCBindings;
+using ObjCRuntime;
+using System;
+
+namespace ObjCRuntime;
+
+static partial class Trampolines
+{
+ // Generate trampolines for compilation
+ [UnmanagedFunctionPointerAttribute (CallingConvention.Cdecl)]
+ [UserDelegateType (typeof (global::ARKit.GetGeolocationCallback))]
+ unsafe internal delegate void DGetGeolocationCallback (global::System.IntPtr block_ptr, global::CoreLocation.CLLocationCoordinate2D coordinate, double altitude, global::ObjCRuntime.NativeHandle error);
+
+ /// This class bridges native block invocations that call into C#
+ static internal class SDGetGeolocationCallback
+ {
+ [Preserve (Conditional = true)]
+ [UnmanagedCallersOnly]
+ [UserDelegateType (typeof (global::ARKit.GetGeolocationCallback))]
+ internal static unsafe void Invoke (global::System.IntPtr block_ptr, global::CoreLocation.CLLocationCoordinate2D coordinate, double altitude, global::ObjCRuntime.NativeHandle error)
+ {
+ var del = global::ObjCRuntime.BlockLiteral.GetTarget (block_ptr);
+ if (del is not null)
+ {
+ del (coordinate, altitude, global::ObjCRuntime.Runtime.GetNSObject (error)!);
+ }
+ }
+
+ internal static unsafe global::ObjCRuntime.BlockLiteral CreateNullableBlock (global::ARKit.GetGeolocationCallback? callback)
+ {
+ if (callback is null)
+ return default (global::ObjCRuntime.BlockLiteral);
+ return CreateBlock (callback);
+ }
+
+ [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
+ internal static unsafe global::ObjCRuntime.BlockLiteral CreateBlock (global::ARKit.GetGeolocationCallback callback)
+ {
+ delegate* unmanaged trampoline = &Invoke;
+ return new global::ObjCRuntime.BlockLiteral (trampoline, callback, typeof (SDGetGeolocationCallback), nameof (Invoke));
+ }
+ }
+ // TODO: generate trampoline for ARKit.GetGeolocationCallback
+
+}
diff --git a/tests/rgen/Microsoft.Macios.Generator.Tests/Microsoft.Macios.Generator.Tests.csproj b/tests/rgen/Microsoft.Macios.Generator.Tests/Microsoft.Macios.Generator.Tests.csproj
index 974bac298d8..706ed2664fc 100644
--- a/tests/rgen/Microsoft.Macios.Generator.Tests/Microsoft.Macios.Generator.Tests.csproj
+++ b/tests/rgen/Microsoft.Macios.Generator.Tests/Microsoft.Macios.Generator.Tests.csproj
@@ -61,9 +61,11 @@
+
+