Skip to content

Research improving finding the constructor to call to create a managed NSObject instance in MSR #18358

@rolfbjarne

Description

@rolfbjarne

Ref: last part of dotnet/runtime#86649 (comment)

When instantiating a managed NSObject instance (or subclass) for an existing Objective-C object

Say we have the following managed class:

class MyObject : NSObject {
    [Export ("doSomething:")]
    public static void DoSomething (NSString something) {}
}

class NSString : NSObject {
    protected NSString (IntPtr handle) : base (handle) {}
}

In this case we do something like:

partial class MyObject {
    class __RegistrarHelper_ {
        [UnmanagedCallersOnly ("__MyObject_DoSomething__")]
        static void DoSomething (IntPtr handle, IntPtr selector, IntPtr arg1)
        {
             // Runtime.GetNSObject:
             // https://github.com/xamarin/xamarin-macios/blob/3dd412daa6b5522029014b0be298f27d751c5f45/src/ObjCRuntime/Runtime.cs#L1516-L1519
             // basically something like this:
             //     if we already have a managed instance for the handle 'handle', return that
             //     otherwise find the constructor that takes an IntPtr (using reflection), and call that constructor
            var arg1Obj = Runtime.GetNSObject ();
                
            MyObject.DoSomething (arg1Obj);
        }
    }
}

This is in some ways very similar to Filip's INativeObject/Selector case from above, except a bit more complex, because Runtime.GetNSObject will look up the actual runtime type of the Objective-C handle, find the closest matching C# type, and create an instance of that type. This might very well be a subclass of the type the caller expects (and this is why we can't just do a new NSString (handle) in the generated code).

Potential solution: we already generate a table to map Objective-C class -> managed type (which we use to find the closest matching C# type for a given Objective-C classr), we could add the token for the IntPtr ctor to table, so that when we find a managed type, we'll find the ctor to call too (or maybe even generate code to call the ctor directly, because calling a method given a token in C# is rather obnoxious)

Metadata

Metadata

Assignees

Labels

performanceIf an issue or pull request is related to performance

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions