MonoTouch binding to ObjectiveC library not workin

2019-05-07 23:31发布

the .h:

#import <Foundation/Foundation.h>

typedef enum _XLBadgeManagedType {
    XLInboxManagedMethod = 0,
    XLDeveloperManagedMethod = 1
} XLBadgeManagedType ;


@interface XLXtifyOptions :NSObject
{
    NSString *xoAppKey;
    BOOL    xoLocationRequired ;
    BOOL    xoBackgroundLocationRequired ;
    BOOL    xoLogging ;
    BOOL    xoMultipleMarkets;
    XLBadgeManagedType xoManageBadge;
}
+ (XLXtifyOptions *)getXtifyOptions;
- (NSString *)getAppKey ;
- (BOOL) isLocationRequired;
- (BOOL) isBackgroundLocationRequired ;
- (BOOL) isLogging ;
- (BOOL) isMultipleMarkets;
- (XLBadgeManagedType)  getManageBadgeType;
- (void)xtLogMessage:(NSString *)header content:(NSString *)message, ...;
@end

the .m:

#import "XLXtifyOptions.h"
#import "XtifyGlobal.h"

static  XLXtifyOptions *xXtifyOptions=nil;

@implementation XLXtifyOptions

+ (XLXtifyOptions *)getXtifyOptions
{
    if (xXtifyOptions==nil) {
        xXtifyOptions=[[XLXtifyOptions alloc]init];
    }
    return xXtifyOptions;
}

-(id)init
{
    if (self = [super init]) {        
        xoAppKey=xAppKey;
        xoLocationRequired=xLocationRequired;
        xoBackgroundLocationRequired=xRunAlsoInBackground ;
        xoLogging =xLogging ;
        xoMultipleMarkets=xMultipleMarkets;
        xoManageBadge=xBadgeManagerMethod;

    }
    return self;
}

- (NSString *)getAppKey
{
    return xoAppKey;
}
- (BOOL) isLocationRequired
{
    return xoLocationRequired;
}
- (BOOL) isBackgroundLocationRequired 
{
    return xoBackgroundLocationRequired;
}
- (BOOL) isLogging 
{
    return xoLogging;
}
- (BOOL) isMultipleMarkets
{
    return xoMultipleMarkets;
}
- (XLBadgeManagedType)  getManageBadgeType
{
    return xoManageBadge;
}
- (void)xtLogMessage:(NSString *)header content:(NSString *)format, ... {
    va_list args;
    va_start(args, format);
    if (xoLogging) {
        NSString *prettyFmt=[NSString stringWithFormat:@"%@ %@", header,format];
        NSLogv(prettyFmt, args);
    }
    va_end(args);
}
@end

Global.h:

#define xAppKey @"abc123"

#define xLocationRequired NO

#define xRunAlsoInBackground FALSE    

#define xBadgeManagerMethod XLInboxManagedMethod 

#define xLogging TRUE

#define xMultipleMarkets FALSE

My binding definition:

[BaseType (typeof (NSObject))]
public interface XLXtifyOptions {

    [Static]
    [Export ("xtifyOptions")]
    XLXtifyOptions Options { get;}

    [Export ("getAppKey")]
    string GetAppKey ();

    [Export ("isLocationRequired")]
    bool IsLocationRequired ();

    [Export ("isBackgroundLocationRequired")]
    bool IsBackgroundLocationRequired ();

    [Export ("isLogging")]
    bool IsLogging ();

    [Export ("isMultipleMarkets")]
    bool IsMultipleMarkets ();

    [Export ("getManageBadgeType")]
    XLBadgeManagedType GetManageBadgeType ();

    //      [Export ("xtLogMessage:content:...")]
    //      void XtLogMessagecontent... (string header, string message,, );
    //      
}

These return null:

XLXtifyOptions.Options;
new XLXtifyOptions().GetAppKey();

The vendors instructions for getting started:

  XLXtifyOptions *anXtifyOptions=[Options getVendorOptions];
  [[TheirClass get ]initilizeXoptions:anVendorOptions];

I hastily tried to rename some things because I'm not sure how much of the vendor's code is ok to paste, so hopefully I didn't confuse matters.

This is related to: Binding #define used as constant

MORE INFORMATION:

If I run this on a device rather than the simulator, I get the following error:

Unhandled managed exception: Wrapper type 'XtifyPush.XLXtifyOptions' is missing its native ObjectiveC class 'XLXtifyOptions'. 

EDIT

re @Stephane: I updated the code to no longer obscure the vendor. What I am binding is: http://developer.xtify.com/display/sdk/Getting+Started+with+Apple+Push+Notification+Service, fwiw. I updated the reference to getXtifyOptions as you recommended, but I have the same result. I got as far as I have with the github library you referenced, but I will keep digging.

The binding I am working on is available at: https://github.com/lordscarlet/monotouch-bindings/tree/master/Xtify

4条回答
再贱就再见
2楼-- · 2019-05-07 23:42

tl;dr the Options class is not compiled

I had a look at your project and the functionality you're trying to bind. It looks like there's 2 parts, the embedded framework, which is distributed precompiled, and some other stuffs (mainly the Options class), including the .h that sets the AppKey, which you are supposed to compile in your app.

Unless you create a minimal xcode project doing that (and exposing a setter for the AppKey), there's no way your binding can work.

Another option is to ditch that part and implement XLXtifyOptions fully in C#, and then you're responsible for setting the AppKey yourself.

UPDATE: Some api calls of the compiled embeddedframework take the Options as parameter, so if you define the Options in C# only, make sure to add an [Export] attribute to every function or property defined in the Options.h file

Hope it helps and you get my point.

查看更多
对你真心纯属浪费
3楼-- · 2019-05-07 23:47

The correct binding for getVendorOptions should looks like this:

[Static]
[Export ("vendorOptions")]
Options Options { get;}

the get part and the Capitalization is done by convention. Look at the code generated for this. GetAppKey is fine as long as you bind it as a method and not a property. Note that it shouldn't return null but throw an exception.

About

MyNamespace.Current;

I don't see any definition for it. So I don't know what's wrong.

At this point, I've some concerns on how your building your native library and including it inside of your managed one (re: the exception on the device). Make sure you're doing it right, look at tons of examples in https://github.com/mono/monotouch-bindings

查看更多
小情绪 Triste *
4楼-- · 2019-05-07 23:56

First of all this API has a horrible design, it relies on #define preprocessor directives for initial configurations like ApiKey, tons of spaces on headers... just to mention a few issues.

You can find a Binding Project here, please test it and tell me if it solves your issues.

https://dl.dropbox.com/u/2058130/random%20stuff/XtifyLib.zip


APIKey has not been set on your bindings.

Inside the SDK headers files, you will find XLXtifyOptions.h and XLXtifyOptions.m this means XLXtifyOptions class does not live inside the Static XtifyPush so I took both files, modified them a little bit and created another static fat (ARMv7, ARMv7s and i386) library called libXtifyLibHelper.a.

This library contains two helper objc messages getXtifyOptionsWithAppKey:locationRequired:backgroundLocationRequired:logging:multipleMarkets:manageBadge: and getXtifyOptionsWithAppKey: which will help you to correctly set the API key.

Please use one of the above helpers to set you API Key, those has been bound as static methods inside XLXtifyOptions class.

As a side note you don't have to worry for libXtifyLibHelper.a it will be automagically (TM) be included inside your DLL when you build the provided project.

Hope this helps

Alex

查看更多
够拽才男人
5楼-- · 2019-05-08 00:02

As you need to build your own managed Options class, is how you could do it (in you Extra.cs file)

public class XLXtifyOptions : NSObject {
    static XLXtifyOptions options;
    [Export ("getXtifyOptions")] //not sure that one will be ever called by obj-C code
    public static XLXtifyOptions XtifyOptions () {
        return options ?? (options = new XLXtifyOptions () {
            appKey = "yourappkey",
        });
    }

    string appKey;

    [Export ("getAppKey")]
    public string GetAppKey () {
        return appKey;
    }

    //same for all the getters

    [Export ("getManageBadgeType")
    public XLBadgeManageType GetManageBadgeType () {
        return manageBadge;
    }

    //Have to check if this is the right way to bind method with variable lengths argument, but that's the idea
    [Export ("xtLogMessage:content:")]
    public void LogMessage (string header, params string[] message)
    {
        //print the message
    }
}

public enum XLBadgeManageType {
    Inbox,
    Developer
}

This should give you an idea...

查看更多
登录 后发表回答