ios - Xamarin.iOS 绑定(bind)库/ native 框架

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

出于某种原因,我需要使用 this我的 Xamarin.iOS 应用程序中的原生框架,问题来了,我不知道如何正确进行绑定(bind)。


因此,据我理解,该框架还使用了另一个框架 framework我有点困惑,我到底需要做什么?


问题:

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

有什么建议吗?谢谢!

最佳答案

好的,我终于制作了一个静态库,但是出了点问题,目前我无法在模拟器 上使用它。 :(

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

  • 我从这个 repository 得到了所有源文件.
  • Xcode IDE 中,我制作了静态库项目,然后我复制了所有从存储库到我的项目的源文件。

  • 通过 Carthage 我已经下载了 this framework (正如我所解释的,源文件使用这个框架)并且我还在 Build Phases -> Copy Files (我选择了框架)中添加了新类别到我的 < strong>静态库。并成功构建(在 Deployment Target 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 中创建了 Binding Library 项目并添加了 Fat Binary Static Library 作为Native Reference(我将在下面显示我的 .csproj 文件)并且我还为框架(我已将其复制到项目路径)放置了相同的链接在 < strong>静态库(也许是多余的?)


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

LinkWith

  • 通过 Objective Sharpie 我已经生成了 ApiDefinition.csStructs.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] 属性检查 Fields 并在解决问题后需要删除这个 Attribute ,还要添加 Protocol 属性等

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

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

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)

_ 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>

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

更新:

只需确保您在链接器上选择了“仅链接框架 SDK”并且正常工作!

关于ios - Xamarin.iOS 绑定(bind)库/ native 框架,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42962939/

相关文章:

ios - 使用 monogame 构建默认 iOS 解决方案时出现错误消息

c# - 在 Xamarin Forms for iOS 的底部和编辑器上添加边框

ios - Xamarin 表单在后台播放歌曲时接收控制中心事件

iphone - 将静态库合并为单个

c++ - 为什么与 Direct X 链接会大大增加我的程序大小?

ios - 从 UIColor 获取 MidColor

ios - AVAudioEngine 在 macOS/iOS 上协调/同步输入/输出时间戳

ios - 使用 IOS Accelerate Framework 对非二次幂图像进行二维信号处理?

ios - 在VueJS应用中使用WavesurferJS,可以播放音频,但波形从未加载到IOS Safari?

c++ - 链接到静态库时出现 "undefined reference"