1

I am creating an Xamarin ios application which uses Socket Mobile’s SocketScan SDK. Created a Binding project to convert the static library to dll. But not able to create instance of ISktScanObject using SktClassFactory.CreateScanObject () method. The instance is not getting created completely due to System.MemberAccessException. Please see the below code

// A 1:1 of ApiHelper's Objective-C open: method
public void Open ()
{
    _deviceInfoList.Clear ();

    if (_noDeviceText != null) {
        _deviceInfoList.Add (_noDeviceText, _noDeviceText);
    }

    if (_scanObjectReceived != null) {
        SktClassFactory.ReleaseScanObject (_scanObjectReceived);
    }
    _scanObjectReceived = SktClassFactory.CreateScanObject (); //Two properties inside _scanObjectReceived are not getting created due to System.MemberAccessException. 

    Task.Run (() => InitializeScanAPIThread ());

    _scanApiOpen = true;
}

Below are the exception messages i get on debugging the _scanObjectReceived object after the line _scanObjectReceived = SktClassFactory.CreateScanObject ();

  1. Msg System.MemberAccessException: Cannot create an instance of ScanAPI.ISktScanMsg because it is an abstract class
  2. Property System.MemberAccessException: Cannot create an instance of ScanAPI.SktScanProperty because it is an abstract class

ApiDefinition for the ISktScanObject interface in binding project is as below:

[Protocol, Model]    
interface ISktScanObject {}

// @protocol ISktScanObject
[Protocol, Model]
[BaseType (typeof (NSObject))]
interface SktScanObject : ISktScanObject
{
    // @required -(id<ISktScanMsg>)Msg;
    [Abstract]
    [Export ("Msg")]
    ISktScanMsg Msg { get; }

    // @required -(id<ISktScanProperty>)Property;
    [Abstract]
    [Export ("Property")]
    SktScanProperty Property { get; }
} 

ApiDefinition for the SktClassFactory interface in binding project is as below:

[BaseType (typeof(NSObject))]
interface SktClassFactory
{
    // +(id<ISktScanObject>)createScanObject;
    [Static]
    [Export ("createScanObject")]
    ISktScanObject CreateScanObject ();

    // +(void)releaseScanObject:(id<ISktScanObject>)scanObj;
    [Static]
    [Export ("releaseScanObject:")]
    void ReleaseScanObject (ISktScanObject scanObj);

    // +(id<ISktScanApi>)createScanApiInstance;
    [Static]
    [Export ("createScanApiInstance")]
    ISktScanApi CreateScanApiInstance ();

    // +(void)releaseScanApiInstance:(id<ISktScanApi>)scanApi;
    [Static]
    [Export ("releaseScanApiInstance:")]
    void ReleaseScanApiInstance (ISktScanApi scanApi);

    // +(id<ISktScanDevice>)createDeviceInstance:(id<ISktScanApi>)scanApi;
    [Static]
    [Export ("createDeviceInstance:")]
    ISktScanDevice CreateDeviceInstance (ISktScanApi scanApi);

    // +(void)releaseDeviceInstance:(id<ISktScanDevice>)deviceInstance;
    [Static]
    [Export ("releaseDeviceInstance:")]
    void ReleaseDeviceInstance (ISktScanDevice deviceInstance);
} 

What needs to be done to properly instantiate the _scanObjectReceived object. Thanks in advance.

valdetero
  • 4,624
  • 1
  • 31
  • 46
  • I am also facing the same issue while creating binding project for Redpark Ethernet cable connectivity for Xamarin.iOS project.Anyone knows how to resolve this?Better to post it in Xamarin forum also. – Ravi Jul 09 '15 at 09:02

2 Answers2

1

This might be long overdue but using the current API I was able to create an iOS binding and call the ISktScanObject & ISktScanApi using:

ScanObject = SktClassFactory.CreateScanObject;
ScanApi = SktClassFactory.CreateScanApiInstance;

This gave me no issues regarding abstract classes.

My ApiDefinition for the SktClassFactory look like this:

// @interface SktClassFactory : NSObject
[BaseType (typeof(NSObject))]
interface SktClassFactory
{
    // +(ISktScanObject *)createScanObject;
    [Static]
    [Export ("createScanObject")]
    ISktScanObject CreateScanObject { get; }

    // +(void)releaseScanObject:(ISktScanObject *)scanObj;
    [Static]
    [Export ("releaseScanObject:")]
    void ReleaseScanObject (ISktScanObject scanObj);

    // +(ISktScanApi *)createScanApiInstance;
    [Static]
    [Export ("createScanApiInstance")]
    ISktScanApi CreateScanApiInstance { get; }

    // +(void)releaseScanApiInstance:(ISktScanApi *)scanApi;
    [Static]
    [Export ("releaseScanApiInstance:")]
    void ReleaseScanApiInstance (ISktScanApi scanApi);

    // +(ISktScanDevice *)createDeviceInstance:(ISktScanApi *)scanApi;
    [Static]
    [Export ("createDeviceInstance:")]
    ISktScanDevice CreateDeviceInstance (ISktScanApi scanApi);

    // +(void)releaseDeviceInstance:(ISktScanDevice *)deviceInstance;
    [Static]
    [Export ("releaseDeviceInstance:")]
    void ReleaseDeviceInstance (ISktScanDevice deviceInstance);
}

Edit: My ISktScanObject looks like this in the ApiDefinition:

// @interface ISktScanObject : NSObject
[BaseType (typeof(NSObject))]
interface ISktScanObject
{
    // -(ISktScanMsg *)Msg;
    [Export ("Msg")]
    ISktScanMsg Msg { get; }

    // -(ISktScanProperty *)Property;
    [Export ("Property")]
    ISktScanProperty Property { get; }
}

Hope this is of any help.

valdetero
  • 4,624
  • 1
  • 31
  • 46
0

I see that you are binding an @protocol, and in Philippes answer the SDK changed to using an @interface for this type, so his answer does not clear much up.

I fixed my problem (with another lib) by adding a skeleton interface (empty interface) for the return type that the library could not instantiate, and changing all return types and parameter types from the class to the interface name.

Notice the added interface and the changed return type.

Before

// @protocol NXProximityZone <NSObject>
[Protocol, Model]
[BaseType(typeof(NSObject))]
interface NXProximityZone
{
    // Methods and properties removed for simplicity
}

// @interface NXProximityManager : NSObject
[BaseType(typeof(NSObject))]
interface NXProximityManager
{
    // +(NSObject<NXProximityZone> *)proximityZoneFromNotification:(NSNotification *)notification;
    [Static]
    [Export("proximityZoneFromNotification:")]
    NXProximityZone ProximityZoneFromNotification(NSNotification notification);

    // Methods and properties removed for simplicity
}

After

// @protocol NXProximityZone <NSObject>
[Protocol, Model]
[BaseType(typeof(NSObject))]
interface NXProximityZone
{
    // Methods and properties removed for simplicity
}

// Skeleton interface
interface INXProximityZone { }

// @interface NXProximityManager : NSObject
[BaseType(typeof(NSObject))]
interface NXProximityManager
{
    // +(NSObject<NXProximityZone> *)proximityZoneFromNotification:(NSNotification *)notification;
    [Static]
    [Export("proximityZoneFromNotification:")]
    INXProximityZone ProximityZoneFromNotification(NSNotification notification);

    // Methods and properties removed for simplicity
}

More information on skeleton interfaces can be found here (Search the page for skeleton)

valdetero
  • 4,624
  • 1
  • 31
  • 46
vrwim
  • 13,020
  • 13
  • 63
  • 118