Xamarin.iOS 绑定库/本机框架 [英] Xamarin.iOS Binding Libraries / Native Frameworks

查看:22
本文介绍了Xamarin.iOS 绑定库/本机框架的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

出于某种原因,我需要使用(正如我所解释的,源文件使用这个框架)并且我还在构建阶段 -> 复制文件中添加了新类别strong>(我选择了框架)到我的 Static Library .并成功构建(在部署目标 10.2)

.

  • 接下来,我制作了 MakeFile 并成功生成了四个 Fat Binary .a 库,没有任何问题.

  • Xcrun 命令显示:

     xcrun -sdk iphoneos lipo -info libOSMapKitAdapter.a胖文件中的架构:libOSMapKitAdapter.a 是:i386 armv7 x86_64 arm64

    • 然后我在 Xamarin 中创建了 Binding Library 项目并添加了 Fat Binary Static Library 作为本机参考(我将在下面显示我的 .csproj 文件),并且我还为链接在 静态库(也许是多余的?)


      另外,我制作了名为 OSTransformation.framework.linkwith.cs 的附加文件,代码为:

    • 通过Objective Sharpie,我生成了ApiDefinition.csStructs.cs.命令:

      sharpie bind --output=OSMapKitAdapter --namespace=OSMapKitAdapter --sdk=iphoneos10.2/MyPath/OSMapKitAdapter/OSMapKitAdapter/*.h

    结果是:

    解析5个头文件...捆绑...[写] ApiDefinitions.cs[写] StructsAndEnums.cs结合分析:自动绑定已完成,但有一些 API 已标记为 [验证] 属性.虽然应审核整个绑定以获得最佳 API 设计实践,请使用以下验证属性提示更仔细地查看 API:ConstantsInterfaceAssociation(1 个实例):没有万无一失的方法来确定外部接口与哪个 Objective-C 接口变量声明可能相关联.这些实例绑定为 [Field]将部分界面中的属性转换为附近的具体界面,以产生更多直观的 API,可能完全消除常量"界面.PlatformInvoke(4 个实例):一般来说,P/Invoke 绑定不像 Objective-C 绑定那样正确或完整(至少目前).您可能需要修复库名称(默认为 '__Internal') 和手动返回/参数类型以符合 C 调用约定目标平台.你可能会发现你甚至不想在你的绑定,但如果您这样做,您可能还想将定义重新定位到更合适的类并公开更强大的类型安全包装器.对于 P/Invoke 指导,请参阅 http://www.mono-project.com/docs/advanced/pinvoke/.一旦您验证了验证属性,您应该将其从绑定源中删除代码.验证属性的存在故意导致构建失败.有关上述验证属性提示的更多信息,请参阅目标通过运行sharpie docs"或访问以下 URL 获取 Sharpie 文档:http://xmn.io/sharpie-docs正在向 Xamarin 提交使用数据...已提交 - 感谢您帮助改进 Objective Sharpie!完毕.

    ApiDefinition.cs 的生成代码如下所示:

    [静态][验证(常量接口关联)]部分接口常量{//extern double OSMapKitAdapterVersionNumber;[字段(OSMapKitAdapterVersionNumber",__Internal")]双 OSMapKitAdapterVersionNumber { 获取;}//extern const unsigned char [] OSMapKitAdapterVersionString;[字段(OSMapKitAdapterVersionString",__Internal")]字节 [] OSMapKitAdapterVersionString { 获取;}}//@interface OSTileOverlay : MKTileOverlay[BaseType (typeof(MKTileOverlay))]接口 OSTileOverlay{//@property (assign, nonatomic) BOOL clipOverlay;[导出(clipOverlay")]bool ClipOverlay { 得到;放;}//-(instancetype _Nonnull)initWithAPIKey:(NSString * _Nonnull)apiKey product:(OSMapProduct)product __attribute__((objc_designated_initializer));[导出 ("initWithAPIKey:product:")][指定初始化程序]IntPtr 构造函数(字符串 apiKey,OSMapProduct 产品);}//@interface OSMapViewRegionRestriction : NSObject[BaseType (typeof(NSObject))]接口 OSMapViewRegionRestriction{//@property (readonly, nonatomic) MKCoordinateRegion initialRegion;[导出(initialRegion")]MKCoordinateRegion InitialRegion { 获取;}//-(void)updateMapViewRegionIfRequired:(MKMapView * _Nonnull)mapView;[导出("updateMapViewRegionIfRequired:")]void UpdateMapViewRegionIfRequired (MKMapView mapView);}//@interface OSMapKitAdapter : NSObject[BaseType (typeof(NSObject))]接口 OSMapKitAdapter{}

    Structs.cs:

    [原生]公共枚举 OSMapProduct : nint{路,户外的,光,夜晚}静态类 CFunctions{//extern NSString * NSStringFromOSMapProduct (OSMapProduct product);[DllImport ("__Internal")][验证(PlatformInvoke)]static extern NSString NSStringFromOSMapProduct (OSMapProduct 产品);//extern CLLocationCoordinate2D OSUpperLeftCorner ();[DllImport ("__Internal")][验证(PlatformInvoke)]静态外部 CLLocationCoordinate2D OSUpperLeftCorner ();//extern CLLocationCoordinate2D OSLowerRightCorner ();[DllImport ("__Internal")][验证(PlatformInvoke)]静态外部 CLLocationCoordinate2D OSLowerRightCorner ();//extern MKMapRect OSMapRectForUK();[DllImport ("__Internal")][验证(PlatformInvoke)]静态外部 MKMapRect OSMapRectForUK ();}

    好的,现在我遇到了编译错误,因为它 shows on official tutorial of Xamarin bindings ,我需要检查 Fields[Verify] 属性和解决后他们的问题需要删除这个 Attribute ,同时添加 Protocol 属性等等.

    ApiDefinition.cs 的新版本:

     [静态]//[验证(常量接口关联)]部分接口常量{//extern double OSMapKitAdapterVersionNumber;[Field("OSMapKitAdapterVersionNumber", "__Internal")]双 OSMapKitAdapterVersionNumber { 获取;}//extern const unsigned char [] OSMapKitAdapterVersionString;[Field("OSMapKitAdapterVersionString", "__Internal")]IntPtr OSMapKitAdapterVersionString { 获取;}}//@interface OSTileOverlay : MKTileOverlay[BaseType(typeof(MKTileOverlay))][协议]接口 OSTileOverlay{//@property (assign, nonatomic) BOOL clipOverlay;[导出(剪辑覆盖")]bool ClipOverlay { 得到;放;}//-(instancetype _Nonnull)initWithAPIKey:(NSString * _Nonnull)apiKey product:(OSMapProduct)product __attribute__((objc_designated_initializer));[导出(initWithAPIKey:产品:")][指定初始化程序]IntPtr Constructor(string apiKey, OSMapProduct product);}//@interface OSMapViewRegionRestriction : NSObject[BaseType(typeof(NSObject))][协议]接口 OSMapViewRegionRestriction{//@property (readonly, nonatomic) MKCoordinateRegion initialRegion;[导出(初始区域")]MKCoordinateRegion InitialRegion { 获取;}//-(void)updateMapViewRegionIfRequired:(MKMapView * _Nonnull)mapView;[导出("updateMapViewRegionIfRequired:")]void UpdateMapViewRegionIfRequired(MKMapView mapView);}//@interface OSMapKitAdapter : NSObject[BaseType(typeof(NSObject))][协议]接口 OSMapKitAdapter{}

    新版结构:

    #if __UNIFIED__[本国的]公共枚举 OSMapProduct : long{路,户外的,光,夜晚}#万一静态类 CFunctions{//extern NSString * NSStringFromOSMapProduct (OSMapProduct product);[DllImport ("__Internal")]//[验证(PlatformInvoke)]static extern NSString NSStringFromOSMapProduct (OSMapProduct 产品);//extern CLLocationCoordinate2D OSUpperLeftCorner ();[DllImport ("__Internal")]//[验证(PlatformInvoke)]静态外部 CLLocationCoordinate2D OSUpperLeftCorner ();//extern CLLocationCoordinate2D OSLowerRightCorner ();[DllImport ("__Internal")]//[验证(PlatformInvoke)]静态外部 CLLocationCoordinate2D OSLowerRightCorner ();//extern MKMapRect OSMapRectForUK();[DllImport ("__Internal")]//[验证(PlatformInvoke)]静态外部 MKMapRect OSMapRectForUK ();}

    问题是我遇到了这个错误:

    <块引用>

    错误 MT5214:本机链接失败,未定义符号:_OSMapKitAdapterVersionNumber.该符号由托管成员 OSTest.Constants.OSMapKitAdapterVersionNumber 引用.请验证是否已引用所有必要的框架并链接了本机库.(MT5214)

    错误 MT5214:本机链接失败,未定义符号:_OSMapKitAdapterVersionString.该符号由托管成员 OSTest.Constants.OSMapKitAdapterVersionString 引用.请验证是否已引用所有必要的框架并链接了本机库.(MT5214)

    错误 MT5202:本机链接失败.请查看构建日志.(MT5202)

    _ Xamarin.Bindings_ 项目的 .csproj 文件看起来如何:

     <Reference Include="系统"/><Reference Include="Xamarin.iOS"/></项目组><项目组><Compile Include="PropertiesAssemblyInfo.cs"/><Compile Include="OSTransformation.framework.linkwith.cs"/></项目组><项目组><ObjcBindingApiDefinition Include="ApiDefinition.cs"/></项目组><项目组><ObjcBindingCoreSource Include="Structs.cs"/></项目组><项目组><NativeReference Include="OSTransformation.framework"><IsCxx>假</IsCxx><种类>框架</种类></NativeReference><NativeReference Include="......MyPathOSMapKitAdapterlibOSMapKitAdapter.a"><种类>静态</种类><SmartLink>错误</SmartLink></NativeReference></项目组><导入项目="$(MSBuildExtensionsPath)XamariniOSXamarin.iOS.ObjCBinding.CSharp.targets"/></项目>

    它在真实设备上工作,但在模拟器上仍然出现这种奇怪的错误.

    更新:

    只要确保您在链接器上选择了仅链接框架 SDK"并正常工作!

    For some reason i need to use this native framework in my Xamarin.iOS app and the problem comes, that i have no idea how to make bindings properly.


    So as i understood correctly, this framework also uses another one framework and i'm little bit confused, what exactly i need to do?


    Questions :

    1. Do i need to implement static library(is this possible to do with native frameworks) as it shows on official documentation of Xamarin ?
    2. Can i make bindings for native framework that is using another framework too or i need to implement them separately?
    3. Maybe i should re-write all these native frameworks into C# version?!? (But here's appears another problem, frameworks uses ObjC and is hard to reproduce in C# for me)
    4. What is the best approach to achieve my goal?(maybe its not described and you can tell me more).

    Any advice? Thanks!

    解决方案

    OK, finally i have made a Static Library, but something is going wrong and i can't use it on Emulator at current moment. :(

    I will explain step by step how i have made an static library :

    • I got all source files from this repository.
    • In Xcode IDE i have made Static Library project and after this i have copied all source files from repository to my project.

    • Via Carthage i have download this framework(As i have explained, source files uses this framework) and also i have added new category in Build Phases -> Copy Files (where i have selected framework) into my Static Library . And builded successfully(On Deployment Target 10.2)

      .

    • Next, i have made MakeFile and successfully generated four Fat Binary .a library's without any problem.

    Xcrun command shows :

     xcrun -sdk iphoneos lipo -info libOSMapKitAdapter.a
     Architectures in the fat file: libOSMapKitAdapter.a are: i386 armv7 x86_64 arm64
    

    • Then i have created Binding Library project in Xamarin and added Fat Binary Static Library as Native Reference(i will show my .csproj file below) and also i have put the same for framework(i have copied inside to project path) that is linked inside of Static Library (maybe it's redundant?)


      Also , i have made additional file that is called OSTransformation.framework.linkwith.cs with code:

    • Via Objective Sharpie i have been generated ApiDefinition.cs and Structs.cs. Command :

      sharpie bind --output=OSMapKitAdapter --namespace=OSMapKitAdapter --sdk=iphoneos10.2 /MyPath/OSMapKitAdapter/OSMapKitAdapter/*.h

    And the result is :

    Parsing 5 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 (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.
    
      PlatformInvoke (4 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/.
    
      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
    
    Submitting usage data to Xamarin...
      Submitted - thank you for helping to improve Objective Sharpie!
    
    Done.
    

    Generated code of ApiDefinition.cs looks like:

    [Static]
        [Verify (ConstantsInterfaceAssociation)]
        partial interface Constants
        {
            // extern double OSMapKitAdapterVersionNumber;
            [Field ("OSMapKitAdapterVersionNumber", "__Internal")]
            double OSMapKitAdapterVersionNumber { get; }
    
            // extern const unsigned char [] OSMapKitAdapterVersionString;
            [Field ("OSMapKitAdapterVersionString", "__Internal")]
            byte[] OSMapKitAdapterVersionString { get; }
        }
    
        // @interface OSTileOverlay : MKTileOverlay
        [BaseType (typeof(MKTileOverlay))]
        interface OSTileOverlay
        {
            // @property (assign, nonatomic) BOOL clipOverlay;
            [Export ("clipOverlay")]
            bool ClipOverlay { get; set; }
    
            // -(instancetype _Nonnull)initWithAPIKey:(NSString * _Nonnull)apiKey product:(OSMapProduct)product __attribute__((objc_designated_initializer));
            [Export ("initWithAPIKey:product:")]
            [DesignatedInitializer]
            IntPtr Constructor (string apiKey, OSMapProduct product);
        }
    
        // @interface OSMapViewRegionRestriction : NSObject
        [BaseType (typeof(NSObject))]
        interface OSMapViewRegionRestriction
        {
            // @property (readonly, nonatomic) MKCoordinateRegion initialRegion;
            [Export ("initialRegion")]
            MKCoordinateRegion InitialRegion { get; }
    
            // -(void)updateMapViewRegionIfRequired:(MKMapView * _Nonnull)mapView;
            [Export ("updateMapViewRegionIfRequired:")]
            void UpdateMapViewRegionIfRequired (MKMapView mapView);
        }
    
        // @interface OSMapKitAdapter : NSObject
        [BaseType (typeof(NSObject))]
        interface OSMapKitAdapter
        {
        }
    

    Structs.cs :

    [Native]
    public enum OSMapProduct : nint
    {
        Road,
        Outdoor,
        Light,
        Night
    }
    
    static class CFunctions
    {
        // extern NSString * NSStringFromOSMapProduct (OSMapProduct product);
        [DllImport ("__Internal")]
        [Verify (PlatformInvoke)]
        static extern NSString NSStringFromOSMapProduct (OSMapProduct product);
    
        // extern CLLocationCoordinate2D OSUpperLeftCorner ();
        [DllImport ("__Internal")]
        [Verify (PlatformInvoke)]
        static extern CLLocationCoordinate2D OSUpperLeftCorner ();
    
        // extern CLLocationCoordinate2D OSLowerRightCorner ();
        [DllImport ("__Internal")]
        [Verify (PlatformInvoke)]
        static extern CLLocationCoordinate2D OSLowerRightCorner ();
    
        // extern MKMapRect OSMapRectForUK ();
        [DllImport ("__Internal")]
        [Verify (PlatformInvoke)]
        static extern MKMapRect OSMapRectForUK ();
    }
    

    OK, now i got compile errors and as it shows on official tutorial of Xamarin bindings , i need to check Fields with [Verify] Attribute and after resolving problem with them needs to remove this Attribute , also add Protocol attribute and etc.

    New version of ApiDefinition.cs :

       [Static]
        //[Verify(ConstantsInterfaceAssociation)]
        partial interface Constants
        {
            // extern double OSMapKitAdapterVersionNumber;
            [Field("OSMapKitAdapterVersionNumber", "__Internal")]
            double OSMapKitAdapterVersionNumber { get; }
    
            // extern const unsigned char [] OSMapKitAdapterVersionString;
            [Field("OSMapKitAdapterVersionString", "__Internal")]
            IntPtr OSMapKitAdapterVersionString { get; }
        }
    
        // @interface OSTileOverlay : MKTileOverlay
        [BaseType(typeof(MKTileOverlay))]
        [Protocol]
        interface OSTileOverlay
        {
            // @property (assign, nonatomic) BOOL clipOverlay;
            [Export("clipOverlay")]
            bool ClipOverlay { get; set; }
    
            // -(instancetype _Nonnull)initWithAPIKey:(NSString * _Nonnull)apiKey product:(OSMapProduct)product __attribute__((objc_designated_initializer));
            [Export("initWithAPIKey:product:")]
            [DesignatedInitializer]
            IntPtr Constructor(string apiKey, OSMapProduct product);
        }
    
        // @interface OSMapViewRegionRestriction : NSObject
        [BaseType(typeof(NSObject))]
        [Protocol]
        interface OSMapViewRegionRestriction
        {
            // @property (readonly, nonatomic) MKCoordinateRegion initialRegion;
            [Export("initialRegion")]
            MKCoordinateRegion InitialRegion { get; }
    
            // -(void)updateMapViewRegionIfRequired:(MKMapView * _Nonnull)mapView;
            [Export("updateMapViewRegionIfRequired:")]
            void UpdateMapViewRegionIfRequired(MKMapView mapView);
        }
    
        // @interface OSMapKitAdapter : NSObject
        [BaseType(typeof(NSObject))]
        [Protocol]
        interface OSMapKitAdapter
        {
        }
    

    New version of Structs :

    #if __UNIFIED__
    [Native]
    public enum OSMapProduct : long
    {
        Road,
        Outdoor,
        Light,
        Night
    }
    #endif 
    static class CFunctions
    {
        // extern NSString * NSStringFromOSMapProduct (OSMapProduct product);
        [DllImport ("__Internal")]
        //[Verify (PlatformInvoke)]
        static extern NSString NSStringFromOSMapProduct (OSMapProduct product);
    
        // extern CLLocationCoordinate2D OSUpperLeftCorner ();
        [DllImport ("__Internal")]
        //[Verify (PlatformInvoke)]
        static extern CLLocationCoordinate2D OSUpperLeftCorner ();
    
        // extern CLLocationCoordinate2D OSLowerRightCorner ();
        [DllImport ("__Internal")]
        //[Verify (PlatformInvoke)]
        static extern CLLocationCoordinate2D OSLowerRightCorner ();
    
        // extern MKMapRect OSMapRectForUK ();
        [DllImport ("__Internal")]
        //[Verify (PlatformInvoke)]
        static extern MKMapRect OSMapRectForUK ();
    }
    

    The problem is that i'm getting this errors :

    Error MT5214: Native linking failed, undefined symbol: _OSMapKitAdapterVersionNumber. This symbol was referenced by the managed member OSTest.Constants.OSMapKitAdapterVersionNumber. Please verify that all the necessary frameworks have been referenced and native libraries linked. (MT5214)

    Error MT5214: Native linking failed, undefined symbol: _OSMapKitAdapterVersionString. This symbol was referenced by the managed member OSTest.Constants.OSMapKitAdapterVersionString. Please verify that all the necessary frameworks have been referenced and native libraries linked. (MT5214)

    Error MT5202: Native linking failed. Please review the build log. (MT5202)

    How looks my .csproj file of_ Xamarin.Bindings_ project :

     <ItemGroup>
        <Reference Include="System" />
        <Reference Include="Xamarin.iOS" />
      </ItemGroup>
      <ItemGroup>
        <Compile Include="PropertiesAssemblyInfo.cs" />
        <Compile Include="OSTransformation.framework.linkwith.cs" />
      </ItemGroup>
      <ItemGroup>
        <ObjcBindingApiDefinition Include="ApiDefinition.cs" />
      </ItemGroup>
      <ItemGroup>
        <ObjcBindingCoreSource Include="Structs.cs" />
      </ItemGroup>
      <ItemGroup>
        <NativeReference Include="OSTransformation.framework">
          <IsCxx>False</IsCxx>
          <Kind>Framework</Kind>
     </NativeReference>
          <NativeReference Include="......MyPathOSMapKitAdapterlibOSMapKitAdapter.a">
            <Kind>Static</Kind>
            <SmartLink>False</SmartLink>
          </NativeReference>
      </ItemGroup>
      <Import Project="$(MSBuildExtensionsPath)XamariniOSXamarin.iOS.ObjCBinding.CSharp.targets" />
    </Project>
    

    It WORKS on real device, but on emulator still get errors this strange errors.

    UPD:

    Just make sure that you have choose "Link framework SDK only" on linker and works as excepted!

    这篇关于Xamarin.iOS 绑定库/本机框架的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆