转载请注明出处,原文网址:http://blog.csdn.net/m_changgong/article/details/8308956 作者:张燕广
主要内容:1)演示使用静态库的第一种方法,即:使用Cocoa Touch Static Library模板;2)研究静态库不同平台下的架构。
关键词:iPhone使用静态库 静态库i386 arm6 arm7
Apple禁止在iPhone中使用动态链接库(Android中可以通过NDK开发,使用JNI技术调用第三方C/C++代码编译的动态链接库libXXX.so),所以要重用代码(第三方库或自己写的C/C++代码库),大致有如下两种方法:
1、将第三方代码库直接加入到使用该代码库的Xcode工程中
1)本人曾做过尝试,将Android产品中底层C代码库移植到iPhone产品中,这些代码库在Android开发时使用NDK技术,用makefile编译的,编译依赖关系比较复杂,直接加入到Xcode工程中编译会有很多错误,解决这些问题实在头大。
2)代码库是Android/IOS共用的,最好还是保持一份代码,如果将这些代码加入到Xcode工程中,自然会加大代码维护成本。
所以,本人认为这种方式实在不可取。
2、使用静态库。
1、将第三方代码库直接加入到使用该代码库的Xcode工程中
1)本人曾做过尝试,将Android产品中底层C代码库移植到iPhone产品中,这些代码库在Android开发时使用NDK技术,用makefile编译的,编译依赖关系比较复杂,直接加入到Xcode工程中编译会有很多错误,解决这些问题实在头大。
2)代码库是Android/IOS共用的,最好还是保持一份代码,如果将这些代码加入到Xcode工程中,自然会加大代码维护成本。
所以,本人认为这种方式实在不可取。
2、使用静态库。
大致有如下两种方式:
1)使用Cocoa Touch Static Library模板
个人认为:这种方式更适合于准备新开发一个C/C++库(比如:准备使用Xcode开发一套纯C/C++代码库用于iOS产品,并且其它平台产品比如Android产品也使用这套代码库)。
如果使用已存在的第三方库代码,用该模板新建一个Static Library工程,然后再将第三方库代码加入到该工程编译,也可能会出现因第三方库代码编译依赖比较负责,而出现很多错误的情况 。
2)使用makefile编译第三方库生成libXXX.a文件(使用makefile来维护代码的编译还是比较方便的),然后在使用该库的工程中引入第三方库的头文件,并将编译好的libXXX.a库加入到Link Binary With Libraries中。
下面演示如何使用第一种方法“Cocoa Touch Static Library模板”这种方式进行静态库的开发。
1、使用Cocoa Touch Static Library模板创建一个静态库工程,命名为:MyLibrary
![](https://img-my.csdn.net/uploads/201212/17/1355744871_9590.png)
![](https://img-my.csdn.net/uploads/201212/17/1355744883_3857.png)
2、新建继承自NSObject的类MyMath
MyMath.h如下:
1)使用Cocoa Touch Static Library模板
个人认为:这种方式更适合于准备新开发一个C/C++库(比如:准备使用Xcode开发一套纯C/C++代码库用于iOS产品,并且其它平台产品比如Android产品也使用这套代码库)。
如果使用已存在的第三方库代码,用该模板新建一个Static Library工程,然后再将第三方库代码加入到该工程编译,也可能会出现因第三方库代码编译依赖比较负责,而出现很多错误的情况 。
2)使用makefile编译第三方库生成libXXX.a文件(使用makefile来维护代码的编译还是比较方便的),然后在使用该库的工程中引入第三方库的头文件,并将编译好的libXXX.a库加入到Link Binary With Libraries中。
下面演示如何使用第一种方法“Cocoa Touch Static Library模板”这种方式进行静态库的开发。
1、使用Cocoa Touch Static Library模板创建一个静态库工程,命名为:MyLibrary
![](https://img-my.csdn.net/uploads/201212/17/1355744871_9590.png)
![](https://img-my.csdn.net/uploads/201212/17/1355744883_3857.png)
2、新建继承自NSObject的类MyMath
MyMath.h如下:
- <span style="font-size:18px;">#import <Foundation/Foundation.h>
- @interface MyMath : NSObject
- +(double)plus:(double)x andY:(double)y;
- +(double)minus:(double)x andY:(double)y;
- +(double)multiply:(double)x andY:(double)y;
- +(double)divide:(double)x andY:(double)y;
- @end</span>
MyMath.m如下:
- <span style="font-size:18px;">#import "MyMath.h"
- @implementation MyMath
- +(double)plus:(double)x andY:(double)y{
- return x+y;
- }
- +(double)minus:(double)x andY:(double)y{
- return x-y;
- }
- +(double)multiply:(double)x andY:(double)y{
- return x*y;
- }
- +(double)divide:(double)x andY:(double)y{
- if(y==0){
- return 0;
- }else{
- return x/y;
- }
- }
- @end</span>
3、新建头文件NumberUtil.h,源文件NumberUtil.c
NumberUtil.h如下:
NumberUtil.h如下:
- <span style="font-size:18px;">#ifndef MyLibrary_NumberUtil_h
- #define MyLibrary_NumberUtil_h
- double getMax(double x,double y);
- double getMin(double x,double y);
- #endif</span>
NumberUtil.c如下:
- <span style="font-size:18px;">#include <stdio.h>
- #include "NumberUtil.h"
- double getMax(double x,double y){
- return x>=y?x:y;
- }
- double getMin(double x,double y){
- return x<=y?x:y;
- }</span>
现在MyLibrary工程结构如下:
![](https://img-my.csdn.net/uploads/201212/17/1355745164_1224.png)
编译,如果没有错误,Products下会生成静态库libMyLibrary.a
4、创建测试工程。新建一个Single View Application工程,命名为MyLibraryTest。
5、确保先关闭工程MyLibrary,然后用鼠标按住工程MyLibrary的工程文件MyLibrary.xcodeproj,将其拖到工程MyLibraryTest下的MyLibraryTest Group下,如下:
![](https://img-my.csdn.net/uploads/201212/17/1355744969_7733.png)
6、在MyLibraryTest工程下新建Group,命名为include,然后将MyLibrary中编写的MyMath.h、NumberUtil.h添加到该Group下(注意:不要选中拷贝,如果拷贝,之后MyLibrary工程修改这两个头文件后还得重新添加),如下:
![](https://img-my.csdn.net/uploads/201212/17/1355745014_3695.png)
7、将静态库libMyLibrary.a加入到工程MyLibraryTest的Link Binary With Libraries中,如下:
![](https://img-my.csdn.net/uploads/201212/17/1355744984_1056.png)
8、现在已经完成对静态库的引用(引入头文件和静态库文件libMyLibrary.a),工程结构如下:
![](https://img-my.csdn.net/uploads/201212/17/1355745002_7580.png)
开始编写测试代码,仅修改了ViewController.m,修改后如下:
![](https://img-my.csdn.net/uploads/201212/17/1355745164_1224.png)
编译,如果没有错误,Products下会生成静态库libMyLibrary.a
4、创建测试工程。新建一个Single View Application工程,命名为MyLibraryTest。
5、确保先关闭工程MyLibrary,然后用鼠标按住工程MyLibrary的工程文件MyLibrary.xcodeproj,将其拖到工程MyLibraryTest下的MyLibraryTest Group下,如下:
![](https://img-my.csdn.net/uploads/201212/17/1355744969_7733.png)
6、在MyLibraryTest工程下新建Group,命名为include,然后将MyLibrary中编写的MyMath.h、NumberUtil.h添加到该Group下(注意:不要选中拷贝,如果拷贝,之后MyLibrary工程修改这两个头文件后还得重新添加),如下:
![](https://img-my.csdn.net/uploads/201212/17/1355745014_3695.png)
7、将静态库libMyLibrary.a加入到工程MyLibraryTest的Link Binary With Libraries中,如下:
![](https://img-my.csdn.net/uploads/201212/17/1355744984_1056.png)
8、现在已经完成对静态库的引用(引入头文件和静态库文件libMyLibrary.a),工程结构如下:
![](https://img-my.csdn.net/uploads/201212/17/1355745002_7580.png)
开始编写测试代码,仅修改了ViewController.m,修改后如下:
- <span style="font-size:18px;">#import "ViewController.h"
- #import "MyMath.h"
- #import "NumberUtil.h"
- @interface ViewController ()
- @end
- @implementation ViewController
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- // Do any additional setup after loading the view, typically from a nib.
- //测试静态库,纯c代码,NumberUtil.h
- [self testNumberUtil];
- //测试静态库,Object-c代码,MyMath类
- [self testMyMath];
- }
- -(void)testNumberUtil{
- double x=20;
- double y= 12;
- double max = getMax(x, y);
- double min = getMin(x, y);
- NSLog(@"max=%.2f,min=%.2f",max,min);
- }
- -(void)testMyMath{
- double x=12;
- double y= 21;
- double plus = [MyMath plus:x andY:y];
- double minus = [MyMath minus:x andY:y];
- double multiply = [MyMath multiply:x andY:y];
- double divide = [MyMath divide:x andY:y];
- NSLog(@"plus=%.2f,minus=%.2f,multiply=%.2f,divide=%.2f",plus,minus,multiply,divide);
- }
- - (void)didReceiveMemoryWarning
- {
- [super didReceiveMemoryWarning];
- // Dispose of any resources that can be recreated.
- }
- @end</span>
9、编译、运行,输出的日志如下:
MyLibraryTest[2997:c07] max=20.00,min=12.00
MyLibraryTest[2997:c07] plus=33.00,minus=-9.00,multiply=252.00,divide=0.57
10、将MyLibrary工程加入到MyLibraryTest中(即:上面将MyLibrary拖入到MyLibraryTest中)到底起了什么作用?
据本人的理解最重要的是为了上面第7步的操作,否则第7步中找不到libMyLibrary.a
这样的话,如果能找到libMyLibrary.a的存放位置,并且在第7步中加入该库,完全没必要将MyLibrary工程加入到MyLibraryTest中。
libMyLibrary.a库存放在哪儿?
在MyLibrary工程中选中libMyLibrary.a,点击右键选择“Show in Finder”
![](https://img-my.csdn.net/uploads/201212/17/1355745241_3684.png)
,可打开libMyLibrary.a的存放位置:
本人机子上的位置是:/Users/duobianxing/Library/Developer/Xcode/DerivedData/MyLibrary-cetahfcogcfucqchjtmezhvutvsk/Build/Products/Debug-iphoneos(如果用模拟器应该是:Debug-iphonesimulator)
![](https://img-my.csdn.net/uploads/201212/17/1355745214_3477.png)
1)将MyLibrary从MyLibraryTest中移除(仅移除引用,不要删除哦)
2)重做第7步操作,点击左下角的Add Othe...,找到上面Debug-iphoneos
下的libMyLibrary.a,加入进来(不要用拷贝方式,如果拷贝进来,一旦生成新的libMyLibrary.a,测试工程中无法自动更新到最新版本)。
11、上面提到本人的libMyLibrary.a库在Debug-iphoneos下(本人用的是真机设备),如果是用模拟器libMyLibrary.a应该在Debug-iphonesimulator下。
MyLibraryTest[2997:c07] max=20.00,min=12.00
MyLibraryTest[2997:c07] plus=33.00,minus=-9.00,multiply=252.00,divide=0.57
10、将MyLibrary工程加入到MyLibraryTest中(即:上面将MyLibrary拖入到MyLibraryTest中)到底起了什么作用?
据本人的理解最重要的是为了上面第7步的操作,否则第7步中找不到libMyLibrary.a
这样的话,如果能找到libMyLibrary.a的存放位置,并且在第7步中加入该库,完全没必要将MyLibrary工程加入到MyLibraryTest中。
libMyLibrary.a库存放在哪儿?
在MyLibrary工程中选中libMyLibrary.a,点击右键选择“Show in Finder”
![](https://img-my.csdn.net/uploads/201212/17/1355745241_3684.png)
,可打开libMyLibrary.a的存放位置:
本人机子上的位置是:/Users/duobianxing/Library/Developer/Xcode/DerivedData/MyLibrary-cetahfcogcfucqchjtmezhvutvsk/Build/Products/Debug-iphoneos(如果用模拟器应该是:Debug-iphonesimulator)
![](https://img-my.csdn.net/uploads/201212/17/1355745214_3477.png)
1)将MyLibrary从MyLibraryTest中移除(仅移除引用,不要删除哦)
2)重做第7步操作,点击左下角的Add Othe...,找到上面Debug-iphoneos
下的libMyLibrary.a,加入进来(不要用拷贝方式,如果拷贝进来,一旦生成新的libMyLibrary.a,测试工程中无法自动更新到最新版本)。
11、上面提到本人的libMyLibrary.a库在Debug-iphoneos下(本人用的是真机设备),如果是用模拟器libMyLibrary.a应该在Debug-iphonesimulator下。
用模拟器和用真机设备生成的静态库libMyLibrary.a是一样的吗?
本人刚做库移植的时候,曾想当然地认为是一样的,结果多浪费了一些时间.
1)用于iphonesimulator的静态库是i386架构的
2)用于iphoneos的静态库是arm架构的,常用的arm6 arm7 arm7s
有个命令lipo可以查看库的信息,如下:
![](https://img-my.csdn.net/uploads/201212/17/1355745108_7317.png)
这就引出了另一个问题:
1)本文介绍的使用Cocoa Touch Static Library模板创建静态库工程(且称为库工程),然后拖入到使用静态库的工程(且称为宿主工程)中,那么当宿主工程运行于模拟器或设备时,那么库工程会自动生成相应版本的静态库(模拟器对应i386,设备对应arm6 arm7)。
2)如果使用“使用makefile编译第三方库生成libXXX.a文件”这种方式,我们需要针对具体运行情景(模拟器或设备)手工编译不同版本的静态库,下一篇再继续介绍。
http://blog.csdn.net/m_changgong/article/details/8308956
本人刚做库移植的时候,曾想当然地认为是一样的,结果多浪费了一些时间.
1)用于iphonesimulator的静态库是i386架构的
2)用于iphoneos的静态库是arm架构的,常用的arm6 arm7 arm7s
有个命令lipo可以查看库的信息,如下:
![](https://img-my.csdn.net/uploads/201212/17/1355745108_7317.png)
这就引出了另一个问题:
1)本文介绍的使用Cocoa Touch Static Library模板创建静态库工程(且称为库工程),然后拖入到使用静态库的工程(且称为宿主工程)中,那么当宿主工程运行于模拟器或设备时,那么库工程会自动生成相应版本的静态库(模拟器对应i386,设备对应arm6 arm7)。
2)如果使用“使用makefile编译第三方库生成libXXX.a文件”这种方式,我们需要针对具体运行情景(模拟器或设备)手工编译不同版本的静态库,下一篇再继续介绍。
http://blog.csdn.net/m_changgong/article/details/8308956