locked
Exposing managed type as protocol to native. RRS feed

  • Question

  • User11612 posted

    I am trying to expose a managed interface to native code as a protocol. I have created a binding for the protocol:

        [Protocol(Name = "Test")]
        public interface Test
        {
           [Export("print")]
           void Print();
        }
    

    with an exported header of:

    @protocol Test
    - (void) print;
    @end
    

    However when I try to get the Protocol type on the native side with:

    @protocol(Test)

    I'm crashing with:

    Failed to marshal the Objective-C object 0x7f81c24230e0 (type: Protocol). Could not find an existing managed instance for this object, nor was it possible to create a new managed instance (because the type 'ObjCRuntime.Protocol' does not have a constructor that takes two (IntPtr, bool) arguments).

    I'm not sure how to resolve this. I've tried creating a class which implements this interface inheriting from NSObject, adding an IntPtr constructor, and instantiating in managed code before the call to @protocol.

    Any help would be appreciated.

    Wednesday, August 26, 2015 9:02 PM

Answers

  • User39 posted

    @adamkemp: The Protocol class is fairly new, so it looks like an oversight that it doesn't work (it's probably never been used in a binding before).

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Tuesday, September 1, 2015 4:22 PM

All replies

  • User11612 posted

    I realize now the problem is with passing the protocol to my managed class:

    [Export("someMethod:")]
    void SomeMethod(Protocol p);
    

    since this fails with the same error message above even for built-in types:

    [myClass someMethod:@protocol(NSObject)]

    Does anybody know the correct way to pass a Protocol to a managed class (not the instance)?

    Thursday, August 27, 2015 12:03 AM
  • User181 posted

    When you built the binding library it should have generated an internal, sealed class called TestWrapper and a public interface called ITest. You should use the ITest interface.

    Monday, August 31, 2015 11:36 PM
  • User11612 posted

    Thanks @adamkemp. However, I'm not trying to pass an instance that conforms to the protocol but instead a descriptor of the protocol. In objc the method would look like:

    - (void) someMethod:(Protocol*)p {
       [self conformsToProtocol:p]; // for example
    }
    

    and could be called:

    [self someMethod:@protocol(Test)];

    Not sure why, but passing @protocol(AnyType) to a bound managed type:

        [Export("someMethod:")]
        void SomeMethod(Protocol p)
    

    fails with the error message above.

    Tuesday, September 1, 2015 12:09 AM
  • User181 posted

    That may be a bug. I suggest reporting it here: http://bugzilla.xamarin.com

    In the meantime you can probably pass in the name of the protocol instead (a string) and then use the Protocol(string) constructor in C# code.

    Tuesday, September 1, 2015 3:59 PM
  • User39 posted

    Try using IntPtr instead:

    [Export("someMethod:")]
    void SomeMethod(IntPtr protocol);
    
    Tuesday, September 1, 2015 4:14 PM
  • User181 posted

    Rolf, is this intended to work as he was trying it? It seems like it should to me.

    Tuesday, September 1, 2015 4:20 PM
  • User39 posted

    @adamkemp: The Protocol class is fairly new, so it looks like an oversight that it doesn't work (it's probably never been used in a binding before).

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Tuesday, September 1, 2015 4:22 PM
  • User11612 posted

    Thanks @adamkemp and @RolfBjarneKvinge works perfectly. I can pass the IntPtr to the Protocol constructor and see that the Name property is set correctly:

    [Export("someMethod:")]
    void SomeMethod(IntPtr protocol)
    {
       Protocol p = new Protocol(protocol);
       Console.Writeline("Got {0}", p.Name);
    }
    
    Tuesday, September 1, 2015 5:28 PM
  • User39 posted

    @adamkemp, the Protocol type is new, so it looks like it's just an oversight that it doesn't work in bindings (it was probably never used that way before)

    Wednesday, September 2, 2015 7:13 AM