关闭

Xamarin iOS开发:绑定第三方iOS Framework

标签: XamariniOSFrameworkProgramming
1323人阅读 评论(1) 收藏 举报

最近尝试用Xamarin开发iOS app的时候发现绑定第三方库的时候比Android麻烦很多。

绑定iOS Framework

首先下载一个iOS Framework:DynamsoftBarcodeReader.framework

在Visual Studio 2015中创建工程iOS bindings library。

xamarin ios binding

Framework里其实是一个静态链接库,把

DynamsoftBarcodeReader.framework\DynamsoftBarcodeReader

重命名成

DynamsoftBarcodeReader.framework\DynamsoftBarcodeReader.a。

把这个静态库拖入到Visual Studio中会自动生成DynamsoftBarcodeReader.linkwith.cs。参考ObjCRuntime.LinkWithAttribute Class配置这个文件。除了指定平台,这里还需要添加一个dylib依赖库:

using System;
using ObjCRuntime;
 
[assembly: LinkWith ("DynamsoftBarcodeReader.a", LinkTarget.ArmV7 | LinkTarget.Simulator, ForceLoad = true, LinkerFlags = "-lc++.1")]

创建一个用于定义接口的ApiDefinition.cs。这个文件如果手动创建会很麻烦,而且容易出错。因此可以借助工具Objective Sharpie,这个工具只能在macOS上安装。

装好之后我们可以用命令生成文件:

sharpie -tlm-do-not-submit bind -framework ~/Desktop/DynamsoftBarcodeReader.framework -sdk iphoneos10.2

把文件拷贝到Visual Studio 2015中。打开文件会发现出现很多的错误,有很多的接口定义上面都有一个[Verify] attributes。如果确认转换没有问题,就可以删除,重新编译就可以通过了。这里是我的:

using System;
using CoreGraphics;
using Foundation;
using ObjCRuntime;
using UIKit;
 
namespace DBRiOS {
     
    [Static]
    partial interface Constants
    {
        // extern double DynamsoftBarcodeReaderVersionNumber;
        [Field ("DynamsoftBarcodeReaderVersionNumber", "__Internal")]
        double DynamsoftBarcodeReaderVersionNumber { get; }
 
        // extern const unsigned char [] DynamsoftBarcodeReaderVersionString;
        [Field ("DynamsoftBarcodeReaderVersionString", "__Internal")]
        NSString DynamsoftBarcodeReaderVersionString { get; }
    }
 
    // @interface Barcode : NSObject
    [BaseType (typeof(NSObject))]
    interface Barcode
    {
        // @property (nonatomic) long format;
        [Export ("format")]
        nint Format { get; set; }
 
        // @property (copy, nonatomic) NSString * formatString;
        [Export ("formatString")]
        string FormatString { get; set; }
 
        // @property (copy, nonatomic) NSString * displayValue;
        [Export ("displayValue")]
        string DisplayValue { get; set; }
 
        // @property (copy, nonatomic) NSData * rawValue;
        [Export ("rawValue", ArgumentSemantic.Copy)]
        NSData RawValue { get; set; }
 
        // @property (copy, nonatomic) NSArray * cornerPoints;
        [Export ("cornerPoints", ArgumentSemantic.Copy)]
        NSObject[] CornerPoints { get; set; }
 
        // @property (nonatomic) CGRect boundingbox;
        [Export ("boundingbox", ArgumentSemantic.Assign)]
        CGRect Boundingbox { get; set; }
 
        // +(long)OneD;
        [Static]
        [Export ("OneD")]
        nint OneD { get; }
 
        // +(long)CODE_39;
        [Static]
        [Export ("CODE_39")]
        nint CODE_39 { get; }
 
        // +(long)CODE_128;
        [Static]
        [Export ("CODE_128")]
        nint CODE_128 { get; }
 
        // +(long)CODE_93;
        [Static]
        [Export ("CODE_93")]
        nint CODE_93 { get; }
 
        // +(long)CODABAR;
        [Static]
        [Export ("CODABAR")]
        nint CODABAR { get; }
 
        // +(long)ITF;
        [Static]
        [Export ("ITF")]
        nint ITF { get; }
 
        // +(long)EAN_13;
        [Static]
        [Export ("EAN_13")]
        nint EAN_13 { get; }
 
        // +(long)EAN_8;
        [Static]
        [Export ("EAN_8")]
        nint EAN_8 { get; }
 
        // +(long)UPC_A;
        [Static]
        [Export ("UPC_A")]
        nint UPC_A { get; }
 
        // +(long)UPC_E;
        [Static]
        [Export ("UPC_E")]
        nint UPC_E { get; }
 
        // +(long)INDUSTRIAL_25;
        [Static]
        [Export ("INDUSTRIAL_25")]
        nint INDUSTRIAL_25 { get; }
 
        // +(long)PDF417;
        [Static]
        [Export ("PDF417")]
        nint PDF417 { get; }
 
        // +(long)DATAMATRIX;
        [Static]
        [Export ("DATAMATRIX")]
        nint DATAMATRIX { get; }
 
        // +(long)QR_CODE;
        [Static]
        [Export ("QR_CODE")]
        nint QR_CODE { get; }
 
        // +(long)UNKNOWN;
        [Static]
        [Export ("UNKNOWN")]
        nint UNKNOWN { get; }
    }
 
    // @interface ReadResult : NSObject
    [BaseType (typeof(NSObject))]
    interface ReadResult
    {
        // @property (nonatomic) int errorCode;
        [Export ("errorCode")]
        int ErrorCode { get; set; }
 
        // @property (copy, nonatomic) NSString * errorString;
        [Export ("errorString")]
        string ErrorString { get; set; }
 
        // @property (nonatomic) NSArray * barcodes;
        [Export ("barcodes", ArgumentSemantic.Assign)]
        Barcode[] Barcodes { get; set; }
    }
 
    // @interface BarcodeReader : NSObject
    [BaseType (typeof(NSObject))]
    interface BarcodeReader
    {
        // +(int)DBRERROR_OK;
        [Static]
        [Export ("DBRERROR_OK")]
        int DBRERROR_OK { get; }
 
        // +(int)DBRERROR_UNKNOWN;
        [Static]
        [Export ("DBRERROR_UNKNOWN")]
        int DBRERROR_UNKNOWN { get; }
 
        // +(int)DBRERROR_NOMEMORY;
        [Static]
        [Export ("DBRERROR_NOMEMORY")]
        int DBRERROR_NOMEMORY { get; }
 
        // +(int)DBRERROR_NULL_POINTER;
        [Static]
        [Export ("DBRERROR_NULL_POINTER")]
        int DBRERROR_NULL_POINTER { get; }
 
        // +(int)DBRERROR_LICENSE_INVALID;
        [Static]
        [Export ("DBRERROR_LICENSE_INVALID")]
        int DBRERROR_LICENSE_INVALID { get; }
 
        // +(int)DBRERROR_LICENSE_EXPIRED;
        [Static]
        [Export ("DBRERROR_LICENSE_EXPIRED")]
        int DBRERROR_LICENSE_EXPIRED { get; }
 
        // +(int)DBRERROR_BARCODE_FORMAT_INVALID;
        [Static]
        [Export ("DBRERROR_BARCODE_FORMAT_INVALID")]
        int DBRERROR_BARCODE_FORMAT_INVALID { get; }
 
        // +(int)DBRERROR_PARAMETER_INVALID;
        [Static]
        [Export ("DBRERROR_PARAMETER_INVALID")]
        int DBRERROR_PARAMETER_INVALID { get; }
 
        // -(id)initWithLicense:(NSString *)license;
        [Export ("initWithLicense:")]
        IntPtr Constructor (string license);
 
        // -(ReadResult *)readSingle:(UIImage *)image barcodeFormat:(long)format;
        [Export ("readSingle:barcodeFormat:")]
        ReadResult ReadSingle (UIImage image, nint format);
 
        // -(void)readSingleAsync:(UIImage *)image barcodeFormat:(long)format sender:(id)sender onComplete:(SEL)callback;
        [Export ("readSingleAsync:barcodeFormat:sender:onComplete:")]
        void ReadSingleAsync (UIImage image, nint format, NSObject sender, Selector callback);
 
        // -(ReadResult *)readSingle:(NSData *)buffer width:(int)width height:(int)height barcodeFormat:(long)format;
        [Export ("readSingle:width:height:barcodeFormat:")]
        ReadResult ReadSingle (NSData buffer, int width, int height, nint format);
 
        // -(void)readSingleAsync:(NSData *)buffer width:(int)width height:(int)height barcodeFormat:(long)format sender:(id)sender onComplete:(SEL)callback;
        [Export ("readSingleAsync:width:height:barcodeFormat:sender:onComplete:")]
        void ReadSingleAsync (NSData buffer, int width, int height, nint format, NSObject sender, Selector callback);
    }
}

编译之后生成DBRiOS.dll

创建iOS App

创建Single View App。把DBRiOS.dll通过Reference加入到工程里。

添加ButtonLableUIImageViewMain.storyboard中:

xamarin storyboard

打开ViewController.cs添加代码:

using System;
 
using UIKit;
using DBRiOS;
 
namespace BarcodeDemo
{
    public partial class ViewController : UIViewController
    {
        public ViewController(IntPtr handle) : base(handle)
        {
        }
 
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();
            // Perform any additional setup after loading the view, typically from a nib.
        }
 
        public override void DidReceiveMemoryWarning()
        {
            base.DidReceiveMemoryWarning();
            // Release any cached data, images, etc that aren't in use.
        }
 
        partial void Button_read_TouchUpInside(UIButton sender)
        {
            BarcodeReader barcodeReader = new BarcodeReader("");
            ReadResult result = barcodeReader.ReadSingle(qrimage.Image, Barcode.QR_CODE);
            Barcode barcode = result.Barcodes[0];
            text.Text = barcode.DisplayValue;
        }
 
        partial void UIButton16_TouchUpInside(UIButton sender)
        {
            text.Text = "";
        }
    }

编译运行程序。选择模拟器或者真机:

xamarin ios barcode reader

遇到的问题

Xamarin Mac Agent连接失败

xamarin failed to connect mac agent

通过Visual Studio 2015连接Mac,如果碰到上面的问题,那应该是Mac上有些相关的东西没有安装。用Xamarin Installer安装xamarin.iosxamarin.macXamarin StudioMonoFramework,再尝试链接应该就好了。

地址无法解析

xamarin ios connection failed

这个问题比较奇怪,有些时候出现可能是因为Mac自动休眠了,有的时候Build就是找不到Mac。这个时候可以试试能不能调用模拟器,如果模拟器被远程启动了,再重新build工程可能就好了。还是不行就重启下Visual Studio。

添加Native Framework Reference

在Visual Studio中是可以直接添加Framework来绑定的,但是Windows上编译出来的库不能用。Mac上的虽然可以用,但是只能运行在真机上。

xamarin ios native reference windows

xamarin ios bindings library macOS

这里的主要问题就是没有提供LinkTarget选项,我用的Framework支持armv7i386x86_64, 和 arm64,但是编译之后生成的DLL尺寸只有原来的一半。

源码

https://github.com/yushulx/xamarin-bind-ios-framework

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:74763次
    • 积分:905
    • 等级:
    • 排名:千里之外
    • 原创:7篇
    • 转载:64篇
    • 译文:0篇
    • 评论:6条