4

I am attempting to create a Xamarin iOS Binding project for an iOS framework library (zip available here) supplied by MasterCard for the purpose of allowing In-App payments. Note that I am currently attempting to bind the framework supplied for the iPhoneOS platform (MasterpassKit_v1_32_build_11\iPhoneOS\MasterPassKit.framework).

I have tried followed the "Binding an iOS Objective-C Library" walkthrough and am currently stuck with the generation of the ApiDefinition file using Objective Sharpie.

Firstly, just to confirm that the iOS framework was valid, I created two native iOS test applications (Objective-C + Swift) and was able to embed and consume the framework successfully.

I then attempted to run Objective Sharpie using the following commands (while in the directory containing the MasterPassKit.framework directory i.e. \MasterpassKit_v1_32_build_11\iPhoneOS\):

  1. I tried using the -framework argument, however this resulted in no files being generated.

    Command:

    sharpie bind -framework MasterPassKit.framework -sdk iphoneos12.1
    

    Output:

    Parsing 1 header files... While building module 'MasterPassKit' imported from /private/var/folders/hq/z29y24gs1_g_5qvp02vr07dh0000gq/T/com.xamarin.ObjectiveSharpie/c3f67365a4014cc0a4618aa6e0caaa87.h:1: In file included from :1: In file included from ./MasterPassKit.framework/Headers/MasterPassKit.h:21: ./MasterPassKit.framework/Headers/MPPresentationController.h:13:1: warning: no 'assign', 'retain', or 'copy' attribute is specified - 'assign' is assumed [-Wobjc-property-no-attribute] @property UIView *dimmingView; ^ ./MasterPassKit.framework/Headers/MPPresentationController.h:13:1: warning: default property attribute 'assign' not appropriate for non-GC object [-Wobjc-property-no-attribute]

    Binding... 2 warnings generated. no types were parsed that could be bound

    Done. Exiting with error code 1.


  1. I then tried using the explicit framework option (with scope specified to the framework header folder). This resulted in a very small ApiDefinition.cs file with only some global constants defined and none of the actual objective-c class definitions.

    Command:

    sharpie bind -output bindingscoped -sdk iphoneos12.1 -scope MasterPassKit.framework/Headers
    

    MasterPassKit.framework/Headers/MasterPassKit.h -c -F .

    Output:

    Parsing 1 header files... In file included from /Users/development/Desktop/iOS/MasterpassKit_v1_32_build_11/iPhoneOS/MasterPassKit.framework/Headers/MasterPassKit.h:21: ./MasterPassKit.framework/Headers/MPPresentationController.h:13:1: warning: no 'assign', 'retain', or 'copy' attribute is specified - 'assign' is assumed [-Wobjc-property-no-attribute] @property UIView *dimmingView; ^ ./MasterPassKit.framework/Headers/MPPresentationController.h:13:1: warning: default property attribute 'assign' not appropriate for non-GC object [-Wobjc-property-no-attribute]

    Binding... [write] ApiDefinitions.cs

    Binding Analysis: Automated binding is complete, but there are a few APIs which have been flagged with [Verify] attributes. While the entire binding should be audited for best API design practices, look more closely at APIs with the following Verify attribute hints:

    ConstantsInterfaceAssociation (1 instance): There's no foolproof way to determine with which Objective-C interface an extern variable declaration may be associated. Instances of these are bound as [Field] properties in a partial interface into a nearby concrete interface to produce a more intuitive API, possibly eliminating the 'Constants' interface altogether.

    Once you have verified a Verify attribute, you should remove it from the binding source code. The presence of Verify attributes intentionally cause build failures. For more information about the Verify attribute hints above, consult the Objective Sharpie documentation by running 'sharpie docs' or visiting the following URL: http://xmn.io/sharpie-docs

    2 warnings generated.

    Done.


  1. I tried using the explicit framework command similar to before, however I omitted the -scope argument. This resulted in massive ApiDefinition.cs and StructsAndEnums.cs files containing what I assume is mostly referenced framework definitions (due to not being scoped to the target frameworks header folder). This also contains numerous verify statements for the core frameworks that would be very time-consuming to work through.

    Command:

    sharpie bind -output bindingnoscoped -sdk iphoneos12.1 MasterPassKit.framework/Headers/MasterPassKit.h -c -F .
    

    Output:

    Parsing 1 header files... In file included from /Users/development/Desktop/iOS/MasterpassKit_v1_32_build_11/iPhoneOS/MasterPassKit.framework/Headers/MasterPassKit.h:21: ./MasterPassKit.framework/Headers/MPPresentationController.h:13:1: warning: no 'assign', 'retain', or 'copy' attribute is specified - 'assign' is assumed [-Wobjc-property-no-attribute] @property UIView *dimmingView; ^ ./MasterPassKit.framework/Headers/MPPresentationController.h:13:1: warning: default property attribute 'assign' not appropriate for non-GC object [-Wobjc-property-no-attribute]

    Binding... [write] ApiDefinitions.cs [write] StructsAndEnums.cs

    Binding Analysis: Automated binding is complete, but there are a few APIs which have been flagged with [Verify] attributes. While the entire binding should be audited for best API design practices, look more closely at APIs with the following Verify attribute hints:

    ConstantsInterfaceAssociation (201 instances): There's no foolproof way to determine with which Objective-C interface an extern variable declaration may be associated. Instances of these are bound as [Field] properties in a partial interface into a nearby concrete interface to produce a more intuitive API, possibly eliminating the 'Constants' interface altogether.

    MethodToProperty (192 instances): An Objective-C method was bound as a C# property due to convention such as taking no parameters and returning a value (non-void return). Often methods like these should be bound as properties to surface a nicer API, but sometimes false-positives can occur and the binding should actually be a method.

    StronglyTypedNSArray (42 instances): A native NSArray* was bound as NSObject[]. It might be possible to more strongly type the array in the binding based on expectations set through API documentation (e.g. comments in the header file) or by examining the array contents through testing. For example, an NSArray* containing only NSNumber* instances can be bound as NSNumber[] instead of NSObject[].

    PlatformInvoke (3251 instances): In general P/Invoke bindings are not as correct or complete as Objective-C bindings (at least currently). You may need to fix up the library name (it defaults to '__Internal') and return/parameter types manually to conform to C calling conventionsfor the target platform. You may find you don't even want to expose the C API in your binding, but if you do, you'll probably also want to relocate the definition to a more appropriate class and expose a stronger type-safe wrapper. For P/Invoke guidance, see http://www.mono-project.com/docs/advanced/pinvoke/.

    InferredFromMemberPrefix (29 instances): The name of this originally anonymous declaration was taken from a common prefix of its members.

    Once you have verified a Verify attribute, you should remove it from the binding source code. The presence of Verify attributes intentionally cause build failures. For more information about the Verify attribute hints above, consult the Objective Sharpie documentation by running 'sharpie docs' or visiting the following URL: http://xmn.io/sharpie-docs

    2 warnings generated.

    Done.


Please let me know if I'm doing anything incorrectly.

Any help would be greatly appreciated!

Update

So I eventually got it working. I first had to flatten the umbrella header's import references then I ran the following command to generate a valid ApiDefinition and Struct file:

sharpie bind Headers/MasterPassKit.h -output MasterPassBindings -namespace MasterPassBindings -sdk iphoneos12.1 -scope Headers Headers/MasterPassKit.h -c -IHeaders -arch arm64
Brett Mealor
  • 111
  • 1
  • 1
  • 7
  • Could you please share github repo which you want to bind? – Yauhen Sampir Mar 01 '19 at 13:56
  • Got it working eventually. Managed to generate the bindings by using the following command and flattening the umbrella header file import references: sharpie bind -output MasterPassBindings -namespace MasterPassBindings -sdk iphoneos12.1 -scope Headers Headers/MasterPassKit.h -c -IHeaders -arch arm64. – Brett Mealor Mar 08 '19 at 11:25
  • Hi! Thank you for your investigation! However, could you actually explain what did you mean by **"I first had to flatten the umbrella header's import reference"**? I am not objective-c/c dev, so have no idea about that. Just need to wrap that library for c#-project using. – Agat Feb 11 '20 at 21:39
  • Also, you should actually answer to your question as you found the solution! It should be paid off! – Agat Feb 11 '20 at 21:39
  • 1
    Hi @Agat. I had to edit the contents of the MasterPassKit.h header file and update the references to the other header files to make them relative to the umbrella header file location (they're all stored in the same folder). E.G. #import gets updated to #import "MPMasterPass.h" Hope that helps! – Brett Mealor Feb 13 '20 at 12:16
  • Yeah. Thanks for the response! Actually, it went well when I just specified the header explicitly with MyLibrary.framework/Headers/MyLibrary.h -scope MyLibrary.framework/Headers -c -F -sdk ... – Agat Feb 13 '20 at 12:18
  • @Agat what did the full command end up looking like? – Pavlos Nov 10 '20 at 14:47
  • Please have a look at the "update" section. – Agat Nov 12 '20 at 11:13

0 Answers0