如何在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。
将Button , Lable和UIImageView添加到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.ios , xamarin.mac , Xamarin Studio和MonoFramework 。 您必须确保在MacOS和Windows上安装了匹配的Xamarin.iOS版本。
无法解析地址
这个问题很奇怪。 有时,它会在重建项目后成功。 有时,无论您重建项目多少次,它都根本不起作用。 如果是这样,您可能必须重新启动Visual Studio才能解决此问题。
有关更多信息,您可以阅读文章连接到Mac。
添加本机框架参考
您是否曾经尝试过直接添加本机框架引用? 我使用Windows Visual Studio和Mac Visual Studio构建了相同的项目,结果却有所不同。 仅从Mac Visual Studio构建的DBRiOS.dll可以工作。
但是,这种方法不能完美地工作。 没有“ LinkTarget ”属性。 DynamsoftBarcodeReader.framework是一个胖框架,支持armv7 , i386 , x86_64和arm64 。
使用框架构建绑定库时,并非所有架构片都被链接。 我发现生成的DBRiOS.dll的大小比原始框架小得多。 而且我只能为设备构建iOS应用,而不能为模拟器构建。
源代码
https://github.com/yushulx/xamarin-bind-ios-framework