Xamarin 引用iOS静态库(.a)文件

我们在开发的的时候常常要引用第三方的库文件或者SDK等。在window平台下有.dll或com组件,在Android可以引用.jar包或.aar包。在Mac(iOS)平台下则可以引用.a或者.framework静态库,在Mac(iOS)原生的环境下引用相对比较简单。使用Xamarin引用iOS静态库相对就比较复杂了,需要做一些特殊的操作。目前Xamarin只能引用.a文件,下面就对Xamarin引用(.a文件)静态库进行一个简单的介绍。

以下内容参考官方文档:https://developer.xamarin.com/guides/cross-platform/macios/binding/

生成自己的静态库

我们在使用第三方的库文件时候,都是已经编译好的库文件。但有时,我们只有代码需要我们自己去生成.a文件。

1、XCode创建静态库项目

打开XCode,菜单File -> New -> Project…,进入项目创建界面。

选择 Framework & Library -> Cocoa Touch Static Library。如下图所示:

image05

之后按照向导一步一步做就可以创建项目了,先假设我创建的工程名字叫做“WosLibDemo”。将源代码(.h和.m文件)导入到项目中。

2、配置项目

添加了源代码之后,我们检查我的的代码引用了哪些系统库(framework)。你可以查看README文件获得信息,或者打开一些相同的项目查考一下。一般应用的framework有 Foundation.framework、UIKit.framework和CoreGraphics.framework。具体哪些库自己搞定。

点击项目查看项目设置界面,选择 yourprojectName target -> Build Phases 然后展开 Link Binary With Libraries 区域。如下图:

image16b

上图点击 + 按键进入添加系统库界面,如下图:

image16c

搜索到我们要添加的系统库,点击 Add 按键即可。还有一些项目的配置,我还不是很清楚,之后熟悉了再补充。

3、生成库文件

在网上查资料说编译项目生成.a 文件直接 Command + B 即可。我亲自试了是可以生成的,项目中生成的位置在Products文件夹下,但是在硬盘中找该文件时却找不到,会保存到默认路径下。如下图,点击生成的.a 文件,右侧高光的路径就是该文件的路径。可以对生成路径设置。

%e5%b1%8f%e5%b9%95%e5%bf%ab%e7%85%a7-2016-09-30-%e4%b8%8b%e5%8d%884-58-14

但是参考官方文档指出,所有版本的iOS 设备的处理器框架是不同的,在iOS设备上处理器就有 armv6 ,armv7,amrv7s,arm64指令集。iOS虚拟机是x86或x86_64框架。为了各个框架通用性,.a 文件要编译出不同框架的版本,然后在将他们合并成一个 .a文件。官方推荐使用Makefile文件来编译项目生成 .a文件。下面是创建Makefile文件的步骤。

  • 打开Mac电脑的终端,使用cd指令  到你所建项目的同级目录下
  • 输入指令  touch Makefile,此时会创建一个空的文件
  • 使用文本编辑器打开 Makefile文件,复制下面的代码,记得将 YOUR-PROJECT-NAME 替换成你项目的名称,最后保存即可
XBUILD=/Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild
PROJECT_ROOT=./YOUR-PROJECT-NAME
PROJECT=$(PROJECT_ROOT)/YOUR-PROJECT-NAME.xcodeproj
TARGET=YOUR-PROJECT-NAME

all: lib$(TARGET).a

lib$(TARGET)-i386.a:
$(XBUILD) -project $(PROJECT) -target $(TARGET) -sdk iphonesimulator -configuration Release clean build
-mv $(PROJECT_ROOT)/build/Release-iphonesimulator/lib$(TARGET).a $@

lib$(TARGET)-armv7.a:
$(XBUILD) -project $(PROJECT) -target $(TARGET) -sdk iphoneos -arch armv7 -configuration Release clean build
-mv $(PROJECT_ROOT)/build/Release-iphoneos/lib$(TARGET).a $@

lib$(TARGET)-arm64.a:
$(XBUILD) -project $(PROJECT) -target $(TARGET) -sdk iphoneos -arch arm64 -configuration Release clean build
-mv $(PROJECT_ROOT)/build/Release-iphoneos/lib$(TARGET).a $@

lib$(TARGET).a: lib$(TARGET)-i386.a lib$(TARGET)-armv7.a lib$(TARGET)-arm64.a
xcrun -sdk iphoneos lipo -create -output $@ $^

clean:
-rm -f *.a *.dll

最后目录是这样的,Makefile文件和项目文件夹在同级目录,如下图:

%e5%b1%8f%e5%b9%95%e5%bf%ab%e7%85%a7-2016-09-30-%e4%b8%8b%e5%8d%885-21-19

创建好了Makefile之后我们就开始编译了库了。同样使用Mac终端,cd到Makefile文件的路径下。然后输入指令 make ,然后就等自动编译了。如果出现什么错误,可能要自己查下原因,比如代码缩进问题。生成成功之后文件夹的这样的,如下图:

%e5%b1%8f%e5%b9%95%e5%bf%ab%e7%85%a7-2016-09-30-%e4%b8%8b%e5%8d%885-27-30

总共生成了四个a文件,前面三个是单个框架下的a文件。第四个 libWoslibDemo.a是前三个文件合并生成的。该文件也是供我们使用的。

封装a文件成Xamarin所用 .dll文件

我们已经生成了iOS的静态库(a文件),下面就要将它封装成Window平台下的.dll文件。请参照以下步骤:

1、在Visual Studio中创建一个绑定iOS类库项目

打开新建项目,选择 Visual C# -> iOS -> Bindings Library(iOS),输入项目名称点击确定即可。如下图:

1

创建了绑定了iOS类库项目之后,项目自动生成两个文件ApiDefinition.cs和 Structs.cs。如下图:

2

ApiDefinition中的内容是必须填写的,不然生成的.Dll是不能调用静态库的方法的。同时代码转换过程比较复杂,需要开发人员认真处理。

2、添加.a文件到项目中

直接将需要封装的a文件添加的项目中即可,添加之后,项目会自动生成一个匹配的 linkwith.cs文件。如图所示:

3

linkwith.cs文件中定义了a文件的所适用的平台,可以根据实际情况进行修改。

3、生成项目

添加了a文件之后,并且完成了ApiDefinition文件的头文件代码转换之后,就可以生成。生成的dll文件可给Xamarin.iOS项目使用。

注意:iOS静态库项目的成功,主要取决于ApiDefinition文件代码转换是否正确,已经类库使用平台是否正确。

使用Objective Sharpie 插件生成 ApiDefinition.cs 文件

如果我们嫌手动写ApiDefinition文件很麻烦。我们可以使用Xamarin提供的Objective Sharpie插件自动生成文件。该插件只能安装在Mac设备上。请参考官方文档:https://developer.xamarin.com/guides/cross-platform/macios/binding/objective-sharpie/

安装了该插件之后,打开Mac终端输入下面代码

sharpie bind --output YourProjectName --namespace YourProjectName --sdk [iphone-os] [full-path-to-project]/WosLibDemo/WosLibDemo/*.h

[iphone-os] 是你手机系统,[full-path-to-project]是你项目的完整路径。

最后*.h表示该路径下的全部头文件,也可以写单个文件的名称。我使用的时候输入指令如下:

sharpie bind --output WosLibDemo -namespace WosLibDemo -sdk iphoneos8.1 /Users/woscms/Documents/TestProject/WosLibDemo/WosLibDemo/*.h

最后生成结果如下图:

%e5%b1%8f%e5%b9%95%e5%bf%ab%e7%85%a7-2016-09-30-%e4%b8%8b%e5%8d%885-51-05

但是自动生成的ApiDefinition文件不一定完全正确,需要开发人员检查,错误的地方要手动修改。