Skip to content

Commit

Permalink
[runtime] Use a custom native -> managed trampoline for calling NSObj…
Browse files Browse the repository at this point in the history
…ect.InvokeConformsToProtocol from the generated static registrar code. (#15830)

This avoids one case where we we embed metadata tokens to a different assembly
in the generated static registrar code.

This is required for supporting per-assembly static registration
(#12067).
  • Loading branch information
rolfbjarne authored Sep 2, 2022
1 parent 0d8eafc commit 7511281
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 3 deletions.
7 changes: 7 additions & 0 deletions runtime/delegates.t4
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,13 @@
WrappedManagedFunction = "AttemptRetainNSObject",
OnlyDynamicUsage = false,
},

new XDelegate ("bool", "bool", "xamarin_invoke_conforms_to_protocol",
"id", "IntPtr", "obj",
"Protocol *", "IntPtr", "protocol"
) {
WrappedManagedFunction = "InvokeConformsToProtocol",
},
};
delegates.CalculateLengths ();
#><#+
Expand Down
8 changes: 8 additions & 0 deletions src/ObjCRuntime/Runtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2143,6 +2143,14 @@ public static string? OriginalWorkingDirectory {
static extern IntPtr xamarin_get_original_working_directory_path ();
#endif // NET || !__MACOS__

static bool InvokeConformsToProtocol (IntPtr handle, IntPtr protocol)
{
var obj = Runtime.GetNSObject (handle);
if (obj is null)
return false;
return obj.ConformsToProtocol (protocol);
}

}

internal class IntPtrEqualityComparer : IEqualityComparer<IntPtr>
Expand Down
11 changes: 8 additions & 3 deletions tests/api-shared/ObjCRuntime/RegistrarTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,16 @@ public void IntPtrCtor ()
try {
ptr = Messaging.IntPtr_objc_msgSend (Class.GetHandle (typeof (IntPtrCtorTestClass)), Selector.GetHandle ("alloc"));
ptr = Messaging.IntPtr_objc_msgSend (ptr, Selector.GetHandle ("init"));
var ex = Assert.Throws<RuntimeException> (() => Messaging.bool_objc_msgSend_IntPtr (ptr, Selector.GetHandle ("conformsToProtocol:"), IntPtr.Zero));
var ex = Assert.Throws<RuntimeException> (() => Messaging.bool_objc_msgSend_IntPtr (ptr, Selector.GetHandle ("testMethod:"), IntPtr.Zero));
var lines = new List<string> ();
#if NET
lines.Add (string.Format ("Failed to marshal the Objective-C object 0x{0} (type: IntPtrCtorTestClass). Could not find an existing managed instance for this object, nor was it possible to create a new managed instance (because the type 'XamarinTests.ObjCRuntime.RegistrarSharedTest+IntPtrCtorTestClass' does not have a constructor that takes one NativeHandle argument).", ptr.ToString ("x")));
#else
lines.Add (string.Format ("Failed to marshal the Objective-C object 0x{0} (type: IntPtrCtorTestClass). Could not find an existing managed instance for this object, nor was it possible to create a new managed instance (because the type 'XamarinTests.ObjCRuntime.RegistrarSharedTest+IntPtrCtorTestClass' does not have a constructor that takes one IntPtr argument).", ptr.ToString ("x")));
#endif
lines.Add ("Additional information:");
lines.Add ("Selector: conformsToProtocol:");
lines.Add ("InvokeConformsToProtocol");
lines.Add ("Selector: testMethod:");
lines.Add ("TestMethod");
foreach (var line in lines)
Assert.That (ex.ToString (), Does.Contain (line), "#message");
} finally {
Expand All @@ -56,6 +56,11 @@ public IntPtrCtorTestClass (int foo)
{
Console.WriteLine ("foo1");
}

[Export ("testMethod:")]
public void TestMethod (IntPtrCtorTestClass p)
{
}
}
}
}
19 changes: 19 additions & 0 deletions tools/common/StaticRegistrar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3340,6 +3340,25 @@ void Specialize (AutoIndentStringBuilder sb, ObjCMethod method, List<Exception>
return;
}

var customConformsToProtocol = method.Selector == "conformsToProtocol:" && method.Method.DeclaringType.Is ("Foundation", "NSObject") && method.Method.Name == "InvokeConformsToProtocol" && method.Parameters.Length == 1;
if (customConformsToProtocol) {
if (Driver.IsDotNet) {
customConformsToProtocol &= method.Parameters [0].Is ("ObjCRuntime", "NativeHandle");
} else {
customConformsToProtocol &= method.Parameters [0].Is ("System", "IntPtr");
}
if (customConformsToProtocol) {
sb.AppendLine ("-(BOOL) conformsToProtocol: (void *) protocol");
sb.AppendLine ("{");
sb.AppendLine ("GCHandle exception_gchandle;");
sb.AppendLine ("BOOL rv = xamarin_invoke_conforms_to_protocol (self, (Protocol *) protocol, &exception_gchandle);");
sb.AppendLine ("xamarin_process_managed_exception_gchandle (exception_gchandle);");
sb.AppendLine ("return rv;");
sb.AppendLine ("}");
return;
}
}

var rettype = string.Empty;
var returntype = method.ReturnType;
var isStatic = method.IsStatic;
Expand Down

4 comments on commit 7511281

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

Please sign in to comment.