Xamarin.iOS绑定库/本机框架

时间:2017-03-22 21:25:55

标签: ios xamarin.ios static-libraries ios-frameworks xamarin.ios-binding

出于某种原因,我需要在我的 Xamarin.iOS 应用中使用this原生框架,问题就出现了,我不知道如何制作绑定得当。

正如我所理解的那样,这个框架还使用了另一个framework,我有点困惑,究竟我需要做什么?

问题:

  1. 我是否需要实现静态库(这可能与 原生框架 有关),如official documentation of Xamarin所示?
  2. 我可以make bindings for native framework使用其他框架,还是需要单独实施?
  3. 也许我应该将所有这些原生框架重新编写成 C# 版本?!? (但是这里出现了另一个问题,框架使用 ObjC ,很难在 C# 中重现我)
  4. 实现目标的最佳方法是什么?(可能没有描述,你可以告诉我更多)。
  5. 有什么建议吗?谢谢!

2 个答案:

答案 0 :(得分:1)

好的,最后我制作了一个静态库,但出现了问题,我现在无法在模拟器上使用它。 :(

我将逐步解释如何制作静态库:

  • 我从这个repository获得了所有源文件。
  • Xcode IDE中,我创建了 静态库项目 ,之后我复制了所有内容源文件从存储库到我的项目。

  • 通过 Carthage 我已下载this framework(正如我所解释的,源文件使用此框架)我还在构建阶段中添加了新类别 - > 复制文件(我已选择框架)到我的 静态库 。并成功构建(在 部署目标 10.2)

    Img

  • 接下来,我已经 MakeFile 并成功生成了四个 Fat Binary .a 库任何问题。

Xcrun 命令显示:

 xcrun -sdk iphoneos lipo -info libOSMapKitAdapter.a
 Architectures in the fat file: libOSMapKitAdapter.a are: i386 armv7 x86_64 arm64
  • 然后我在Xamarin中创建了 绑定库 项目,并添加了 Fat二进制静态库 原生参考 (我将在下面显示我的.csproj文件)并且我已经将相同的框架(我已经复制到项目路径中)放在< strong> 静态库 (也许它是多余的?)


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

LinkWith

  • 通过 目标Sharpie 我已生成 ApiDefinition.cs Structs.cs 。 命令:

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

结果是:

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.

生成的 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

[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 ();
}

好的,现在我收到了编译错误,因为它shows on official tutorial of Xamarin bindings,我需要用 [Verify] 属性检查字段,并在解决问题后解决它们要删除此属性,还要添加协议属性等。

新版 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
    {
    }

新版 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 ();
}

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

  

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

     

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

     

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

如何查看 _ Xamarin.Bindings _ 项目的 .csproj 文件:

 <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>
在实际设备上

WORKS ,但在模拟器上仍会出现这种奇怪错误。

UPD:

请确保您已在链接器上选择“仅链接框架SDK”,并作为例外工作!

答案 1 :(得分:0)

这个库是用纯粹的ObjC编写的。 Swift只写了一个例子。 鉴于库代码相对较小,我建议你重新写入C#

相关问题