Forum Xamarin Xamarin.iOS

Binding for SkypeForBusiness SDK crash without any error message.

YeHeYeHe USMember

Hi,

I am trying to create a Obj-C binding for the SkypeForBusiness SDK
Basically, i am following this guide

The generated API definition is
`using CoreAnimation;
using CoreGraphics;
using Foundation;
using ObjCRuntime;
using SkypeForBusiness;
using UIKit;

namespace SkypeForBusiness
{
// @interface SfBAlert : NSObject
[BaseType (typeof(NSObject))]
[DisableDefaultCtor]
interface SfBAlert
{
// @property (readonly) SfBAlertType type;
[Export ("type")]
SfBAlertType Type { get; }

    // @property (readonly) SfBAlertLevel level;
    [Export ("level")]
    SfBAlertLevel Level { get; }

    // @property (readonly) NSError * _Nonnull error;
    [Export ("error")]
    NSError Error { get; }
}

// @protocol SfBAlertDelegate
[Protocol, Model]
interface SfBAlertDelegate
{
    // @required -(void)didReceiveAlert:(SfBAlert * _Nonnull)alert;
    [Abstract]
    [Export ("didReceiveAlert:")]
    void DidReceiveAlert (SfBAlert alert);
}

// @interface SfBApplication : NSObject
[BaseType (typeof(NSObject))]
[DisableDefaultCtor]
interface SfBApplication
{
    // @property (readonly) SfBConfigurationManager * _Nonnull configurationManager;
    [Export ("configurationManager")]
    SfBConfigurationManager ConfigurationManager { get; }

    // @property (readonly) SfBDevicesManager * _Nonnull devicesManager;
    [Export ("devicesManager")]
    SfBDevicesManager DevicesManager { get; }

    [Wrap ("WeakAlertDelegate")]
    [NullAllowed]
    SfBAlertDelegate AlertDelegate { get; set; }

    // @property (readwrite, weak) id<SfBAlertDelegate> _Nullable alertDelegate;
    [NullAllowed, Export ("alertDelegate", ArgumentSemantic.Weak)]
    NSObject WeakAlertDelegate { get; set; }

    // +(instancetype _Nullable)sharedApplication;
    [Static]
    [Export ("sharedApplication")]
    [return: NullAllowed]
    SfBApplication SharedApplication ();

    // -(SfBConversation * _Nullable)joinMeetingAnonymousWithUri:(NSURL * _Nonnull)meetingUri displayName:(NSString * _Nonnull)displayName error:(NSError * _Nullable * _Nullable)error;
    [Export ("joinMeetingAnonymousWithUri:displayName:error:")]
    [return: NullAllowed]
    SfBConversation JoinMeetingAnonymousWithUri (NSUrl meetingUri, string displayName, [NullAllowed] out NSError error);
}

// @interface SfBConversationService : NSObject
[BaseType (typeof(NSObject))]
interface SfBConversationService
{
    // -(BOOL)start:(NSError * _Nullable * _Nullable)error;
    [Export ("start:")]
    bool Start ([NullAllowed] out NSError error);

    // @property (readonly) BOOL canStart;
    [Export ("canStart")]
    bool CanStart { get; }

    // -(BOOL)stop:(NSError * _Nullable * _Nullable)error;
    [Export ("stop:")]
    bool Stop ([NullAllowed] out NSError error);

    // @property (readonly) BOOL canStop;
    [Export ("canStop")]
    bool CanStop { get; }
}

// @interface SfBAudioService : SfBConversationService
[BaseType (typeof(SfBConversationService))]
[DisableDefaultCtor]
interface SfBAudioService
{
    // @property (readonly) BOOL isOnHold;
    [Export ("isOnHold")]
    bool IsOnHold { get; }

    // -(BOOL)setHold:(BOOL)hold error:(NSError * _Nullable * _Nullable)error;
    [Export ("setHold:error:")]
    bool SetHold (bool hold, [NullAllowed] out NSError error);

    // @property (readonly) BOOL canSetHold;
    [Export ("canSetHold")]
    bool CanSetHold { get; }
}

// @interface SfBChatService : SfBConversationService
[BaseType (typeof(SfBConversationService))]
[DisableDefaultCtor]
interface SfBChatService
{
    // -(BOOL)sendMessage:(NSString * _Nonnull)text error:(NSError * _Nullable * _Nullable)error;
    [Export ("sendMessage:error:")]
    bool SendMessage (string text, [NullAllowed] out NSError error);

    // @property (readonly) BOOL canSendMessage;
    [Export ("canSendMessage")]
    bool CanSendMessage { get; }

    // -(BOOL)sendIsTyping:(NSError * _Nullable * _Nullable)error;
    [Export ("sendIsTyping:")]
    bool SendIsTyping ([NullAllowed] out NSError error);
}

// @interface SfBConfigurationManager : NSObject
[BaseType (typeof(NSObject))]
[DisableDefaultCtor]
interface SfBConfigurationManager
{
    // @property (readwrite) uint32_t maxVideoChannels;
    [Export ("maxVideoChannels")]
    uint MaxVideoChannels { get; set; }

    // @property (readwrite, nonatomic) BOOL requireWifiForAudio;
    [Export ("requireWifiForAudio")]
    bool RequireWifiForAudio { get; set; }

    // @property (readwrite, nonatomic) BOOL requireWifiForVideo;
    [Export ("requireWifiForVideo")]
    bool RequireWifiForVideo { get; set; }
}

// @interface SfBConversation : NSObject
[BaseType (typeof(NSObject))]
[DisableDefaultCtor]
interface SfBConversation
{
    // @property (readonly) SfBConversationState state;
    [Export ("state")]
    SfBConversationState State { get; }

    // @property (readonly) NSArray<SfBParticipant *> * _Nonnull remoteParticipants;
    [Export ("remoteParticipants")]
    SfBParticipant[] RemoteParticipants { get; }

    // @property (readonly) SfBParticipant * _Nonnull selfParticipant;
    [Export ("selfParticipant")]
    SfBParticipant SelfParticipant { get; }

    // @property (readonly) SfBParticipant * _Nullable dominantSpeaker;
    [NullAllowed, Export ("dominantSpeaker")]
    SfBParticipant DominantSpeaker { get; }

    // @property (readonly) SfBHistoryService * _Nonnull historyService;
    [Export ("historyService")]
    SfBHistoryService HistoryService { get; }

    // @property (readonly) SfBChatService * _Nonnull chatService;
    [Export ("chatService")]
    SfBChatService ChatService { get; }

    // @property (readonly) SfBAudioService * _Nonnull audioService;
    [Export ("audioService")]
    SfBAudioService AudioService { get; }

    // @property (readonly) SfBVideoService * _Nonnull videoService;
    [Export ("videoService")]
    SfBVideoService VideoService { get; }

    // @property (readonly) NSString * _Nonnull subject;
    [Export ("subject")]
    string Subject { get; }

    // -(BOOL)leave:(NSError * _Nullable * _Nullable)error;
    [Export ("leave:")]
    bool Leave ([NullAllowed] out NSError error);

    // @property (readonly) BOOL canLeave;
    [Export ("canLeave")]
    bool CanLeave { get; }

    [Wrap ("WeakAlertDelegate")]
    [NullAllowed]
    SfBAlertDelegate AlertDelegate { get; set; }

    // @property (readwrite, weak) id<SfBAlertDelegate> _Nullable alertDelegate;
    [NullAllowed, Export ("alertDelegate", ArgumentSemantic.Weak)]
    NSObject WeakAlertDelegate { get; set; }
}

// @interface SfBConversationActivityItem : NSObject
[BaseType (typeof(NSObject))]
[DisableDefaultCtor]
interface SfBConversationActivityItem
{
    // @property (readonly) SfBActivityType type;
    [Export ("type")]
    SfBActivityType Type { get; }

    // @property (readonly) NSDate * _Nonnull timestamp;
    [Export ("timestamp")]
    NSDate Timestamp { get; }

    // @property (readonly) SfBActivityStatus status;
    [Export ("status")]
    SfBActivityStatus Status { get; }
}

// @interface SfBMessageActivityItem : SfBConversationActivityItem
[BaseType (typeof(SfBConversationActivityItem))]
interface SfBMessageActivityItem
{
    // @property (readonly) SfBMessageDirection direction;
    [Export ("direction")]
    SfBMessageDirection Direction { get; }

    // @property (readonly) SfBPerson * _Nullable sender;
    [NullAllowed, Export ("sender")]
    SfBPerson Sender { get; }

    // @property (readonly) NSString * _Nonnull text;
    [Export ("text")]
    string Text { get; }

    // @property (readonly) SfBMessageFormat format;
    [Export ("format")]
    SfBMessageFormat Format { get; }
}

// @interface SfBParticipantActivityItem : SfBConversationActivityItem
[BaseType (typeof(SfBConversationActivityItem))]
interface SfBParticipantActivityItem
{
    // @property (readonly) SfBPerson * _Nonnull person;
    [Export ("person")]
    SfBPerson Person { get; }
}

// @interface SfBSpeaker : NSObject
[BaseType (typeof(NSObject))]
[DisableDefaultCtor]
interface SfBSpeaker
{
    // @property (readwrite) SfBSpeakerEndpoint activeEndpoint;
    [Export ("activeEndpoint", ArgumentSemantic.Assign)]
    SfBSpeakerEndpoint ActiveEndpoint { get; set; }
}

// @interface SfBCamera : NSObject
[BaseType (typeof(NSObject))]
[DisableDefaultCtor]
interface SfBCamera
{
    // @property (readonly) SfBCameraType type;
    [Export ("type")]
    SfBCameraType Type { get; }

    // @property (readonly) NSString * _Nonnull description;
    [Export ("description")]
    string Description { get; }
}

// @interface SfBDevicesManager : NSObject
[BaseType (typeof(NSObject))]
[DisableDefaultCtor]
interface SfBDevicesManager
{
    // @property (readonly) SfBSpeaker * _Nonnull selectedSpeaker;
    [Export ("selectedSpeaker")]
    SfBSpeaker SelectedSpeaker { get; }

    // @property (readonly) NSArray<SfBCamera *> * _Nonnull cameras;
    [Export ("cameras")]
    SfBCamera[] Cameras { get; }
}

[Static]
[Verify (ConstantsInterfaceAssociation)]
partial interface Constants
{
    // extern NSString *const SfBErrorDomain;
    [Field ("SfBErrorDomain", "__Internal")]
    NSString SfBErrorDomain { get; }

    // extern NSString *const SfBErrorSeverityKey;
    [Field ("SfBErrorSeverityKey", "__Internal")]
    NSString SfBErrorSeverityKey { get; }

    // extern NSString *const SfBErrorSeveritySuccess;
    [Field ("SfBErrorSeveritySuccess", "__Internal")]
    NSString SfBErrorSeveritySuccess { get; }

    // extern NSString *const SfBErrorSeverityWarning;
    [Field ("SfBErrorSeverityWarning", "__Internal")]
    NSString SfBErrorSeverityWarning { get; }

    // extern NSString *const SfBErrorSeverityError;
    [Field ("SfBErrorSeverityError", "__Internal")]
    NSString SfBErrorSeverityError { get; }
}

// @interface SfBHistoryService : NSObject
[BaseType (typeof(NSObject))]
[DisableDefaultCtor]
interface SfBHistoryService
{
    // @property (readonly) NSArray<SfBConversationActivityItem *> * _Nonnull activityItems;
    [Export ("activityItems")]
    SfBConversationActivityItem[] ActivityItems { get; }
}

// @interface SfBParticipant : NSObject
[BaseType (typeof(NSObject))]
[DisableDefaultCtor]
interface SfBParticipant
{
    // @property (readonly) SfBParticipantState state;
    [Export ("state")]
    SfBParticipantState State { get; }

    // @property (readonly) SfBParticipantRole role;
    [Export ("role")]
    SfBParticipantRole Role { get; }

    // @property (readonly) SfBParticipantChat * _Nonnull chat;
    [Export ("chat")]
    SfBParticipantChat Chat { get; }

    // @property (readonly) SfBParticipantAudio * _Nonnull audio;
    [Export ("audio")]
    SfBParticipantAudio Audio { get; }

    // @property (readonly) SfBParticipantVideo * _Nonnull video;
    [Export ("video")]
    SfBParticipantVideo Video { get; }

    // @property (readonly) SfBPerson * _Nonnull person;
    [Export ("person")]
    SfBPerson Person { get; }
}

// @interface SfBParticipantService : NSObject
[BaseType (typeof(NSObject))]
interface SfBParticipantService
{
    // @property (readonly) SfBParticipantServiceState state;
    [Export ("state")]
    SfBParticipantServiceState State { get; }
}

// @interface SfBParticipantAudio : SfBParticipantService
[BaseType (typeof(SfBParticipantService))]
[DisableDefaultCtor]
interface SfBParticipantAudio
{
    // @property (readonly) BOOL isSpeaking;
    [Export ("isSpeaking")]
    bool IsSpeaking { get; }

    // @property (readonly) BOOL isOnHold;
    [Export ("isOnHold")]
    bool IsOnHold { get; }

    // @property (readonly) BOOL isMuted;
    [Export ("isMuted")]
    bool IsMuted { get; }

    // -(BOOL)setMuted:(BOOL)muted error:(NSError * _Nullable * _Nullable)error;
    [Export ("setMuted:error:")]
    bool SetMuted (bool muted, [NullAllowed] out NSError error);

    // @property (readonly) BOOL canSetMuted;
    [Export ("canSetMuted")]
    bool CanSetMuted { get; }
}

// @interface SfBParticipantChat : SfBParticipantService
[BaseType (typeof(SfBParticipantService))]
[DisableDefaultCtor]
interface SfBParticipantChat
{
    // @property (readonly) BOOL isTyping;
    [Export ("isTyping")]
    bool IsTyping { get; }
}

// @interface SfBVideoStream : NSObject
[BaseType (typeof(NSObject))]
[DisableDefaultCtor]
interface SfBVideoStream
{
    // @property (readonly) CGSize dimensions;
    [Export ("dimensions")]
    CGSize Dimensions { get; }

    // -(BOOL)render:(NSError * _Nullable * _Nullable)error;
    [Export ("render:")]
    bool Render ([NullAllowed] out NSError error);

    // -(BOOL)setAutoFitMode:(SfBVideoStreamAutoFitMode)mode error:(NSError * _Nullable * _Nullable)error;
    [Export ("setAutoFitMode:error:")]
    bool SetAutoFitMode (SfBVideoStreamAutoFitMode mode, [NullAllowed] out NSError error);
}

// @interface SfBParticipantVideo : SfBParticipantService
[BaseType (typeof(SfBParticipantService))]
[DisableDefaultCtor]
interface SfBParticipantVideo
{
    // @property (readonly) BOOL isPaused;
    [Export ("isPaused")]
    bool IsPaused { get; }

    // -(SfBVideoStream * _Nullable)subscribe:(CAEAGLLayer * _Nonnull)renderTarget error:(NSError * _Nullable * _Nullable)error;
    [Export ("subscribe:error:")]
    [return: NullAllowed]
    SfBVideoStream Subscribe (CAEAGLLayer renderTarget, [NullAllowed] out NSError error);

    // @property (readonly) BOOL canSubscribe;
    [Export ("canSubscribe")]
    bool CanSubscribe { get; }

    // -(BOOL)unsubscribe:(NSError * _Nullable * _Nullable)error;
    [Export ("unsubscribe:")]
    bool Unsubscribe ([NullAllowed] out NSError error);
}

// @interface SfBPerson : NSObject
[BaseType (typeof(NSObject))]
[DisableDefaultCtor]
interface SfBPerson
{
    // @property (readonly) NSURL * _Nonnull sipUri;
    [Export ("sipUri")]
    NSUrl SipUri { get; }

    // @property (readonly) NSString * _Nonnull displayName;
    [Export ("displayName")]
    string DisplayName { get; }
}

// @interface SfBVideoPreview : NSObject
[BaseType (typeof(NSObject))]
[DisableDefaultCtor]
interface SfBVideoPreview
{
    // @property (readonly) CGSize dimensions;
    [Export ("dimensions")]
    CGSize Dimensions { get; }
}

// @interface SfBVideoService : SfBConversationService
[BaseType (typeof(SfBConversationService))]
[DisableDefaultCtor]
interface SfBVideoService
{
    // @property (readonly) SfBCamera * _Nullable activeCamera;
    [NullAllowed, Export ("activeCamera")]
    SfBCamera ActiveCamera { get; }

    // -(BOOL)setActiveCamera:(SfBCamera * _Nonnull)camera error:(NSError * _Nullable * _Nullable)error;
    [Export ("setActiveCamera:error:")]
    bool SetActiveCamera (SfBCamera camera, [NullAllowed] out NSError error);

    // @property (readonly) BOOL canSetActiveCamera;
    [Export ("canSetActiveCamera")]
    bool CanSetActiveCamera { get; }

    // -(BOOL)setPaused:(BOOL)paused error:(NSError * _Nullable * _Nullable)error;
    [Export ("setPaused:error:")]
    bool SetPaused (bool paused, [NullAllowed] out NSError error);

    // @property (readonly) BOOL canSetPaused;
    [Export ("canSetPaused")]
    bool CanSetPaused { get; }

    // -(SfBVideoPreview * _Nullable)preview:(UIView * _Nonnull)renderTarget error:(NSError * _Nullable * _Nullable)error;
    [Export ("preview:error:")]
    [return: NullAllowed]
    SfBVideoPreview Preview (UIView renderTarget, [NullAllowed] out NSError error);
}

}
`

And the StructusAndEnums files are:
`using System;
using ObjCRuntime;

namespace SkypeForBusiness
{
public enum SfBAlertType
{
Messaging = 101,
UcwaObjectModel = 200,
AutoDiscovery = 201,
SignIn = 300,
SignOut = 301,
Connectivity = 302,
Conferencing = 500,
ParticipantMute = 504,
ParticipantUnmute = 505,
ConferenceUnexpectedDisconnect = 514,
Video = 600,
VideoOverWiFiBlocked = 602,
VideoGenericError = 603,
Voice = 700,
CallFailed = 708,
ConferenceIsRecording = 1004,
Communication = 1100,
Common = 1200
}

public enum SfBAlertLevel
{
    Error,
    Warning,
    Info
}

public enum SfBConversationState
{
    Idle,
    Establishing,
    InLobby,
    Established
}

public enum SfBActivityType
{
    ParticipantJoined,
    ParticipantLeft,
    Message,
    Unknown
}

public enum SfBActivityStatus
{
    Pending,
    Failed,
    Succeeded
}

public enum SfBMessageDirection
{
    Incoming,
    Outgoing
}

public enum SfBMessageFormat
{
    SfBMessageFormatText
}

public enum SfBSpeakerEndpoint
{
    Loudspeaker = 1,
    NonLoudspeaker = 2
}

public enum SfBCameraType
{
    Unknown = 1,
    External,
    FrontFacing,
    BackFacing
}

[Native]
public enum SfBError : nint
{
    InvalidArgument = 536870915,
    ActionNotAvailable = 587726849
}

public enum SfBParticipantRole
{
    Attendee,
    Leader
}

public enum SfBParticipantState
{
    InLobby,
    Connected
}

public enum SfBParticipantServiceState
{
    Disconnected,
    Connecting,
    Connected
}

public enum SfBVideoStreamAutoFitMode
{
    Fit,
    Crop
}

}

`

I have made some changes to them.

  1. Change [Protocol, Model] to [BaseType(typeof(NSObject))] [Model] as told in the guide

[BaseType(typeof(NSObject))] [Model] interface SfBAlertDelegate

  1. Change nint in the StructsAndEnums to int cuz nint is not recognized.

public enum SfBError : int { InvalidArgument = 536870915, ActionNotAvailable = 587726849 }

When I import the generated DLL to a Xamarin.iOS project, everything gets built.

Add a using SkypeForBusiness in the beginning is fine.
But when I reference any class in the namespace the app crash right after it is launched.

For example,
private SfBApplication sfb;

The message in the Application Output pad is:

'Press enter to terminate the applicatoin'

I have tried to set a breakpoint at the start of the applicaiton which is static void Main(string[] args),
It won't stop and will crash quickly.

Any suggestion and help.

BTW, when I use this command to generate ApiDefinition.

sharpie bind -framework ~/Desktop/SkypeForBusiness.framework -sdk iphoneos9.3 -output SkypeForBusiness -namespace SkypeForBusiness

I removed the Info.plist file in the framework folder because the -sdk option couldn't override the config in the Info.plist and sharpie throw error for
not finding iphonesimulator9.3. I do have this SDK. So I guess it is just a sharpie bug.

Posts

  • ggammonggammon USBeta ✭✭

    It looks like the SkypeForBusiness SDK has two different .framework's for the Simulator and Device implementations. Have you tried building a universal library and referencing that from within your binding project?

    It's done something like this

    lipo -create "pathToLib1/SkypeForBusiness.a" "pathToLib2/SkypeForBusiness.a" -output "outputPath/SkypeForBusiness.a"

  • YeHeYeHe USMember

    Yes I have.

  • pietdevries12pietdevries12 Member ✭✭

    Hi @YeHe.

    You've probably long forgotten this, but did you ever solve your Skype for Business bindings?
    I'm trying to do the same, but am failing miserably...

    If you solved it, would you please share your solution?

Sign In or Register to comment.