如何在Windows上使用Xamarin绑定Fat iOS框架

使用Xamarin开发Android项目时,我没有遇到任何麻烦。 但是,使用Xamarin构建iOS应用程序时,这是完全不同的体验—更复杂。 在本文中,我将分享我使用Xamarin绑定DynamsoftBarcodeReader.framework的经验。

将iOS框架与Xamarin绑定

下载

DynamsoftBarcodeReader.framework是用于条形码检测的SDK。

用Linkwith.cs文件链接依赖项

Visual Studio 2015中创建一个iOS绑定库项目:

DynamsoftBarcodeReader.framework \ DynamsoftBarcodeReader重命名为DynamsoftBarcodeReader.framework \ DynamsoftBarcodeReader.a ,然后将静态库拖到项目中。 IDE将自动生成相应的DynamsoftBarcodeReader.linkwith.cs文件:

DynamsoftBarcodeReader.framework依赖于libc ++。1.dylib 。 参考ObjCRuntime.LinkWithAttribute类, DynamsoftBarcodeReader.linkwith.cs编写如下:

using System;

using ObjCRuntime;

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

使用Objective Sharpie生成ApiDefinition.cs

ApiDefinition.cs是定义API合同的地方,该文件描述了如何将基本的Objective-C API投影到C#中。 您可以为库手动定义所有API,也可以使用仅在macOS上运行的Objective Sharpie自动生成定义。

这是为DynamsoftBarcodeReader.framework生成ApiDeifinition.cs的命令:

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

您必须修改生成的文件,因为Objective Sharpie使用[Verify]属性来注释API。 确认API之后,您可以删除[verify]的行。 这是我的:

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 ; } 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 ; } FormatString { get ; set ; }

// @property (copy, nonatomic) NSString * displayValue;

[Export ("displayValue")]

string DisplayValue { get ; set ; } 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 ; } ErrorCode { get ; set ; }

// @property (copy, nonatomic) NSString * errorString;

[Export ("errorString")]

string ErrorString { get ; set ; } ErrorString { get ; set ; }

// @property (nonatomic) NSArray * barcodes;

[Export ("barcodes", ArgumentSemantic.Assign)]

Barcode[] Barcodes { get ; set ; }

}

// @interface BarcodeReader : NSObject

[BaseType ( typeof (NSObject))]

BarcodeReader interface

{

// +(int)DBRERROR_OK;

[Static]

[Export ("DBRERROR_OK")]

int DBRERROR_OK { get ; } DBRERROR_OK { get ; }

// +(int)DBRERROR_UNKNOWN;

[Static]

[Export ("DBRERROR_UNKNOWN")]

int DBRERROR_UNKNOWN { get ; } DBRERROR_UNKNOWN { get ; }

// +(int)DBRERROR_NOMEMORY;

[Static]

[Export ("DBRERROR_NOMEMORY")]

int DBRERROR_NOMEMORY { get ; } DBRERROR_NOMEMORY { get ; }

// +(int)DBRERROR_NULL_POINTER;

[Static]

[Export ("DBRERROR_NULL_POINTER")]

int DBRERROR_NULL_POINTER { get ; } DBRERROR_NULL_POINTER { get ; }

// +(int)DBRERROR_LICENSE_INVALID;

[Static]

[Export ("DBRERROR_LICENSE_INVALID")]

int DBRERROR_LICENSE_INVALID { get ; } DBRERROR_LICENSE_INVALID { get ; }

// +(int)DBRERROR_LICENSE_EXPIRED;

[Static]

[Export ("DBRERROR_LICENSE_EXPIRED")]

int DBRERROR_LICENSE_EXPIRED { get ; } DBRERROR_LICENSE_EXPIRED { get ; }

// +(int)DBRERROR_BARCODE_FORMAT_INVALID;

[Static]

[Export ("DBRERROR_BARCODE_FORMAT_INVALID")]

int DBRERROR_BARCODE_FORMAT_INVALID { get ; } DBRERROR_BARCODE_FORMAT_INVALID { get ; }

// +(int)DBRERROR_PARAMETER_INVALID;

[Static]

[Export ("DBRERROR_PARAMETER_INVALID")]

int DBRERROR_PARAMETER_INVALID { get ; } 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条形码阅读器应用

在Visual Studio 2015中创建一个iOS Single View App ,并将DBRiOS.dll添加到References。

ButtonLableUIImageView添加到Main.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 = "";

}

}

}

在设备或模拟器上构建并运行iOS条码读取器。

故障排除

无法连接Xamarin Mac代理

如果遇到上述错误,请检查是否在macOS上安装了所有必需的软件。 您可以使用Xamarin安装程序下载xamarin.iosxamarin.macXamarin StudioMonoFramework 。 您必须确保在MacOS和Windows上安装了匹配的Xamarin.iOS版本。

无法解析地址

这个问题很奇怪。 有时,它会在重建项目后成功。 有时,无论您重建项目多少次,它都根本不起作用。 如果是这样,您可能必须重新启动Visual Studio才能解决此问题。

有关更多信息,您可以阅读文章连接到Mac。

添加本机框架参考

您是否曾经尝试过直接添加本机框架引用? 我使用Windows Visual StudioMac Visual Studio构建了相同的项目,结果却有所不同。 仅从Mac Visual Studio构建的DBRiOS.dll可以工作。

但是,这种方法不能完美地工作。 没有“ LinkTarget ”属性。 DynamsoftBarcodeReader.framework是一个胖框架,支持armv7i386x86_64arm64

使用框架构建绑定库时,并非所有架构片都被链接。 我发现生成的DBRiOS.dll的大小比原始框架小得多。 而且我只能为设备构建iOS应用,而不能为模拟器构建。

源代码

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