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 @@ + +