Why does Objective Sharpie output a huge ApiDefinition.cs file for a very small library?

JasperJianJasperJian USMember ✭✭

I've recently started using Objective Sharpie to bind iOS libraries and I'm following the walkthrough on the developer site. I am able to bind the files successfully but the output ApiDefinition.cs file and Structs.cs file is huge, about 60 000 lines long. This is not meant to be the case. Can anyone tell me how to fix this issue please?

Best Answer

Answers

  • I've had exactly the same issue... The ApiDefinition.cs and Structs.cs files are so huge that Visual Studio for Mac becomes unusably slow when trying to so much as look at these files.

    I first tried the "Walkthrough" provided by Xamarin, and thought perhaps the issue was that they were exposing APIs from all header files (*.h). So as a test, I built an extremely simple static library in Objective-C with just a single method in a single class with a single header file. Even this resulted in tens of thousands of lines of code in both ApiDefinitions.cs and Structs.cs.

    Even worse, when I finally located the code that was supposed to expose my one method, it had exposed it as a read-only property rather than a method. I wound up writing my ApiDefinitions.cs file manually, exposing my one method, and that worked fine... But I would like to understand how to use Objective Sharpie so that these things can be automated to some extent.

    Is this a bug in Objective Sharpie, or are we just using it wrong? Any information would be greatly appreciated.

    @JasperJian - If the library you're converting is Objective-C, I've seen other members in this forum suggesting a project called "objc-automatic" as a more successful route. Perhaps that will help.

  • JasperJianJasperJian USMember ✭✭

    Thanks Chris, I'll try to limit the scope of the binding and see if that makes a difference.

  • Thanks very much, @Chrisvanwyk!

    I finally found a reference to the scope variable when in an "advanced" document. I have left feedback on the Walkthrough page, asking that the Objective Sharpie command be updated to talk about the Scope argument. As a beginner, the humongous files generated are not only intimidating and incomprehensible, they make Visual Studio so insanely slow that you can't even easily look through the files to try to understand what the heck all those lines are for. Hopefully the walkthrough will get an update... By hiding the scope argument in an article marked "Advanced", it leaves beginners like myself clueless. :)

  • AnuragShukla.2829AnuragShukla.2829 USMember
    edited December 2017

    Hello @Chrisvanwyk
    I also have a similar issue. I have a static library with two header files.
    It generates a massive size api definition and struct.cs file. I don't think limiting the scope will matter in this case.
    On the side note, what does limiting the scope really means? Is it asking the sharpie tool to no look in to framework definitions as well?
    Curious.
    Just to get the background of the issue, I have this ePOS library and header files from EPSON POS SDK and I want to use it in my Xamarin Native (iOS and Android) projects. I was able to generate the bindings, but to be honest it is so daunting, I don't know where to begin.
    Any pointer in right direction is appreciated.

    Anurag

    I cannot add link to the file.

  • NashZhouNashZhou USMember ✭✭✭
    edited January 1

    @JasperJian @JonathanBachelor @Chrisvanwyk Is there any documentation on how to solve this problem? I'm having some trouble too and it never occurred in version 3.3 (I updated to 3.4 today)

    I created a really simple header file

    #import <UIKit/UIKit.h>
    
    @interface MyView : UIView
    
    -(void)myMethod;
    
    @end 
    

    Objective Sharpie should only have to generate this in ApiDefinitions

    // @interface MyView : UIView
    [BaseType (typeof(UIView))]
    interface MyView
    {
        // -(void)myMethod;
        [Export ("myMethod")]
        void MyMethod ();
    }
    

    but now it binds everything needed for UIKit

    //** I'm seeing stuff like this **//
    [Static]
    [Verify (ConstantsInterfaceAssociation)]
    partial interface Constants
    {
        // extern _RuneLocale _DefaultRuneLocale;
        [Field ("_DefaultRuneLocale", "__Internal")]
        _RuneLocale _DefaultRuneLocale { get; }
    }
    
    // @interface UIView : UIResponder <NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem, UITraitEnvironment, UICoordinateSpace, UIFocusItem, CALayerDelegate>
    [iOS (2,0)]
    [BaseType (typeof(UIResponder))]
    interface UIView : INSCoding, IUIAppearance, IUIAppearanceContainer, IUIDynamicItem, IUITraitEnvironment, IUICoordinateSpace, IUIFocusItem, ICALayerDelegate
    {
        //** Every property and function for the UIView class **//
    }
    

    If I remove #include <UIKit/UIKit.h> as well as the UIView inheritance I get what I expect however I won't get the [BaseType (typeof(UIView))]

    If I remove #include <UIKit/UIKit.h> while keeping the UIView inheritance I get cannot find interface declaration for 'UIView' from Objective Sharpie.

    Is there a reason why every file in #include and #import are now part of ApiDefinitions and StructsAndEnums? This wasn't a problem for 3.3

  • ChrisvanwykChrisvanwyk USXamarin Team, University, XamUProfessors, Developer Group Leader Xamurai

    @NashZhou from our documentation site:

    You will notice that we passed a -scope build/Headers argument to Objective Sharpie. Because C and Objective-C libraries must #import or #include other header files that are implementation details of the library and not API you wish to bind, the -scope argument tells Objective Sharpie to ignore any API that is not defined in a file somewhere within the -scope directory.

    My suggestion is to include the -scope parameter now by default.

  • NashZhouNashZhou USMember ✭✭✭

    @Chrisvanwyk
    I might need more clarification on the proper command.

    sharpie bind -output TempBinding -namespace TempBinding -sdk iphoneos11.2 \
        -scope build/Headers ~/Desktop/TempHeaderFolder/*.h \
        -c -Ibuild/Headers -arch arm64
    

    is the command I'm currently using and I still get bindings from UIKit. Objective Sharpie 3.4 is able to find the MyView header file located in TempHeaderFolder but I still get everything from UIKit. The only solution I have right now is downgrading to version 3.3 or weed out all of UIKit's bindings. Could you clarify what command should be used if scope isn't working?

  • ChrisvanwykChrisvanwyk USXamarin Team, University, XamUProfessors, Developer Group Leader Xamurai

    @NashZhou

    I created the header file as you specified above and tested with Sharpie 3.4.0-c0f0e73

    My header file is located in this folder /Users/xxx/Projects/BindingTest/Headers running the following command from the /Users/xxx/Projects/BindingTest folder:

    sharpie bind -output TempBinding -namespace TempBinding -sdk iphoneos11.2 -scope Headers Headers/*.h -c -IHeaders -arch arm64

    This created an ApiDefinitions.cs in /Users/xxx/Projects/BindingTest/TempBinding.

    The contents from the ApiDefinitions.cs file is as follows:

    namespace TempBinding
    {
        // @interface MyView : UIView
        [BaseType (typeof(UIView))]
        interface MyView
        {
            // -(void)myMethod;
            [Export ("myMethod")]
            void MyMethod ();
        }
    }
    

    I believe you need to change your command line so that the -scope as well as the -l folder path passed to clang match the ~/Desktop/TempHeaderFolder your header file is located in .

  • MatteoMonizzaMatteoMonizza ITBeta ✭✭

    Hi, I'm going crazy in binding a framework. First I get a huge file so I set the scope and the files seem better, but I always get an error on a file and no way to get the binding to work.. My command is: sharpie bind -sdk iphoneos11.3 -output Bindings -namespace TestBindingNamirial -scope NamirialFEA.framework/Headers NamirialFEA.framework/Headers/*.h -c -INamirialFEA.framework/Headers -arch arm64 -v
    Can you https://forums.xamarin.com/profile/Chrisvanwyk the framework give some hints?

  • MatteoMonizzaMatteoMonizza ITBeta ✭✭

    Here is the framework @Chrisvanwyk

  • ChrisvanwykChrisvanwyk USXamarin Team, University, XamUProfessors, Developer Group Leader Xamurai

    Hi @MatteoMonizza

    Leave your sharpie command line statement as is.

    Edit NamirialFEA.framework/Headers/NamirialFEA.h and change all imports from #import <NamirialFEA/*.h> to #import <*.h>

    This worked for me.

  • MatteoMonizzaMatteoMonizza ITBeta ✭✭

    Done, now I can run it but when I try to call the first method TestBindingNamirial.FCManager.GetManager().Init(); it does nothing and if I set a breakpoint it never stop..

  • mayank_kulsmayank_kuls Member

    @Chrisvanwyk said:
    Hi @JonathanBachelor

    I have found that you need to limit the scope of the binding. Use the -scope pathTo/Headers parameter, assuming you have not done so already. If this does not help, share your simple lib and I'll have a look.

    I am also assuming Sharpie used a [Verify] attribute on the generated property? I am also assuming that your method had no parameters? In this case the convention is to convert the method into a property. If you do not want this syntax, you are welcome to modify the definition. This is why the [Verify] attribute is there.

    Best

    I am new in Xamarin development. Can you please give me command how I can limit to scope in our project. We are getting 25000 lines in .cs file

  • Emixam23Emixam23 USMember ✭✭✭

    Hi !

    There is my terminal output/input:

    MacBook-Pro-de-Emixam23:XamarinIOS_Bindings emixam23$ sharpie bind -output Test2 -namespace Test2 -sdk iphoneos11.2 -scope Test2/build Test2/Test2/*.h -c -Ibuild/Headers -arch arm64
    Parsing 1 header files...
    
    Binding...
      no types were parsed that could be bound
    
    Done. Exiting with error code 1.
    

    It doesn't work and I am not sure to understand why.. I have XCode 9.2 because otherwise it crash directly with an unhandled exception...

    I tried with others parameters but it generates 18k lines of code for APIDefinitions and 25k for StructsAndEnums

    MacBook-Pro-de-Emixam23:XamarinIOS_Bindings emixam23$ sharpie bind -output Test2 -namespace Test2 -sdk iphoneos11.2 Test2/Test2/Test2.h
    Parsing 1 header files...
    
    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 (101 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 (121 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 (21 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 (2407 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 (24 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
    
    Done.
    

    I only have that code:

    Test2.h

    //
    //  Test2.h
    //  Test2
    //
    //  Created by Emixam23 on 07/08/2018.
    //  Copyright © 2018 Noname. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    
    @interface Test2 : NSObject
    
    + (void) PrintCustomLog : (NSString*) data;
    
    @end
    

    Test2.m

    //
    //  Test2.m
    //  Test2
    //
    //  Created by Emixam23 on 07/08/2018.
    //  Copyright © 2018 Noname. All rights reserved.
    //
    
    #import "Test2.h"
    
    @implementation Test2
    
    + (void) PrintCustomLog : (NSString*) data
    {
        NSLog(@"%@", data);
    }
    
    @end
    

    I am just learning so I might have missed something but I am stuck atm :/

  • ankhelborankhelbor Member ✭✭

    I am trying to bind my swift framework with Xamarin. I am using objective Sharpie for this.

    I have set 'Enable Bitcode' to 'No' in the framework.
    Built the framework for running.
    Use the following command for binding the header file.

  • ankhelborankhelbor Member ✭✭

    @ankhelbor said:
    I am trying to bind my swift framework with Xamarin. I am using objective Sharpie for this.

    I have set 'Enable Bitcode' to 'No' in the framework.
    Built the framework for running.
    Use the following command for binding the header

    https://test-dpc.com/ file.

    SnapTube TubeMate Test Dpc

  • ankhelborankhelbor Member ✭✭

    @ankhelbor said:

    @ankhelbor said:
    I am trying to bind my swift framework with Xamarin. I am using objective Sharpie for this.

    I have set 'Enable Bitcode' to 'No' in the framework.
    Built the framework for running.
    Use the following command for binding the header

    SnapTube TubeMate Test Dpc

Sign In or Register to comment.