简体   繁体   English

Xamarin.iOS 绑定库/本机框架

[英]Xamarin.iOS Binding Libraries / Native Frameworks

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.出于某种原因,我需要在我的Xamarin.iOS应用程序中使用这个本机框架,但问题来了,我不知道如何正确进行绑定。


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 ?我是否需要实现静态库(这可能与本机框架有关),因为它在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?!?也许我应该将所有这些原生框架重写为C#版本?!? (But here's appears another problem, frameworks uses ObjC and is hard to reproduce in C# for me) (但这里出现了另一个问题,框架使用ObjC并且对我来说很难在C# 中重现)
  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.Xcode IDE 中,我创建了静态库项目,之后我将所有源文件从存储库复制到了我的项目中。

  • 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 .通过Carthage,我已经下载了这个框架(正如我已经解释过的,源文件使用这个框架),并且我还在Build Phases -> Copy Files (我选择了框架)到我的静态库中添加了新类别。 And builded successfully(On Deployment Target 10.2)并成功构建(在部署目标10.2 上)

    图像 . .

  • Next, i have made MakeFile and successfully generated four Fat Binary .a library's without any problem.接下来,我制作了MakeFile并成功生成了四个Fat Binary .a库,没有任何问题。

Xcrun command shows : Xcrun命令显示:

 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?)然后我在 Xamarin 中创建了Binding Library项目并添加了Fat Binary Static Library作为Native Reference (我将在下面显示我的 .csproj 文件),并且我已经将相同的框架(我已复制到项目路径中)放在里面静态库(也许是多余的?)


    Also , i have made additional file that is called OSTransformation.framework.linkwith.cs with code:此外,我还使用代码制作了名为OSTransformation.framework.linkwith.cs 的附加文件:

链接方式

  • Via Objective Sharpie i have been generated ApiDefinition.cs and Structs.cs .通过Objective Sharpie,我生成了ApiDefinition.csStructs.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: 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")]
        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 :结构.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.好的,现在我遇到了编译错误,正如它在 Xamarin 绑定的官方教程中显示的那样,我需要检查具有[验证]属性的字段,在解决它们的问题后需要删除此属性,还添加协议属性等。

New version of ApiDefinition.cs : 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.错误 MT5214:本机链接失败,未定义符号:_OSMapKitAdapterVersionNumber。 This symbol was referenced by the managed member OSTest.Constants.OSMapKitAdapterVersionNumber.此符号由托管成员 OSTest.Constants.OSMapKitAdapterVersionNumber 引用。 Please verify that all the necessary frameworks have been referenced and native libraries linked.请验证是否已引用所有必要的框架并链接了本机库。 (MT5214) (MT5214)

Error MT5214: Native linking failed, undefined symbol: _OSMapKitAdapterVersionString.错误 MT5214:本机链接失败,未定义符号:_OSMapKitAdapterVersionString。 This symbol was referenced by the managed member OSTest.Constants.OSMapKitAdapterVersionString.此符号由托管成员 OSTest.Constants.OSMapKitAdapterVersionString 引用。 Please verify that all the necessary frameworks have been referenced and native libraries linked.请验证是否已引用所有必要的框架并链接了本机库。 (MT5214) (MT5214)

Error MT5202: Native linking failed.错误 MT5202:本机链接失败。 Please review the build log.请查看构建日志。 (MT5202) (MT5202)

How looks my .csproj file of _ Xamarin.Bindings_ project :我的.csproj文件的_ Xamarin.Bindings_项目看起来如何:

 <ItemGroup>
    <Reference Include="System" />
    <Reference Include="Xamarin.iOS" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Properties\AssemblyInfo.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="..\..\..\MyPath\OSMapKitAdapter\libOSMapKitAdapter.a">
        <Kind>Static</Kind>
        <SmartLink>False</SmartLink>
      </NativeReference>
  </ItemGroup>
  <Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.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!只需确保您在链接器上选择了“仅链接框架 SDK”并正常工作!

This library is written in pure ObjC.这个库是用纯 ObjC 编写的。 There is only one example written by Swift.只有一个例子是 Swift 写的。 In view of the library code is relatively small, I recommend you re-write into C #鉴于库代码比较少,建议你重新写成C#

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM