Skip to content

Commit

Permalink
[ObjCRuntime] Work around a difference in .NET where Type.IsInterface…
Browse files Browse the repository at this point in the history
… doesn't work the same way for byref types.

Ref: dotnet/runtime#39068

Fixes this test:

    MonoTouchFixtures.ObjCRuntime.RegistrarTest
        [FAIL] RefOutTest_INSCoding : System.InvalidCastException : Unable to cast object of type 'Foundation.NSString' to type 'Foundation.INSCoding&'.
            at ObjCRuntime.Runtime.GetINativeObject(IntPtr ptr, Boolean owns, Type target_type, Type implementation)
            at ObjCRuntime.Runtime.GetINativeObject(IntPtr ptr, Boolean owns, Type target_type)
            at ObjCRuntime.Runtime.GetINativeObject_Dynamic(IntPtr ptr, Boolean owns, IntPtr type_ptr)
            at ObjCRuntime.Runtime.get_inative_object_dynamic(IntPtr obj, Boolean owns, IntPtr type, Int32& exception_gchandle)
            --- End of stack trace from previous location ---
            at MonoTouchFixtures.ObjCRuntime.RegistrarTest.RefOutTest_INSCoding() in /Users/rolf/work/maccore/squashed-onedotnet/xamarin-macios/tests/monotouch-test/ObjCRuntime/RegistrarTest.cs:line 2908
            at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
  • Loading branch information
rolfbjarne committed Aug 24, 2020
1 parent 9d30e6e commit 45431c9
Showing 1 changed file with 20 additions and 2 deletions.
22 changes: 20 additions & 2 deletions src/ObjCRuntime/Runtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1358,7 +1358,14 @@ static Type LookupINativeObjectImplementation (IntPtr ptr, Type target_type, Typ
}
}

if (implementation.IsInterface)
var interface_check_type = implementation;
#if NET
// https://github.com/dotnet/runtime/issues/39068
if (interface_check_type.IsByRef)
interface_check_type = interface_check_type.GetElementType ();
#endif

if (interface_check_type.IsInterface)
implementation = FindProtocolWrapperType (implementation);

return implementation;
Expand All @@ -1382,8 +1389,14 @@ static INativeObject GetINativeObject (IntPtr ptr, bool owns, Type target_type,
}

if (o != null) {
var interface_check_type = target_type;
#if NET
// https://github.com/dotnet/runtime/issues/39068
if (interface_check_type.IsByRef)
interface_check_type = interface_check_type.GetElementType ();
#endif
// found an existing object, but with an incompatible type.
if (!target_type.IsInterface) {
if (!interface_check_type.IsInterface) {
// if the target type is another class, there's nothing we can do.
throw new InvalidCastException (string.Format ("Unable to cast object of type '{0}' to type '{1}'.", o.GetType ().FullName, target_type.FullName));
}
Expand Down Expand Up @@ -1456,6 +1469,11 @@ public static T GetINativeObject<T> (IntPtr ptr, bool forced_type, bool owns) wh

private static Type FindProtocolWrapperType (Type type)
{
#if NET
// https://github.com/dotnet/runtime/issues/39068
if (type.IsByRef)
type = type.GetElementType ();
#endif
if (type == null || !type.IsInterface)
return null;

Expand Down

0 comments on commit 45431c9

Please sign in to comment.