(android/swig实现)用c/c++混合编程方式为ios/android实现一个自绘日期选择控件(三)
三、Android版本:
1、ndk开发必要的基础知识:
原本想配套写一下ndk开发方面的基础和步骤,但老实说,这也并非三言两语就能描述清楚的,好在网上已经有现存的文章了,经过该作者同意,本人就引用一下:@zzyyppqq thanks
2014年的时候,基本都是使用eclipse来开发,使用android mk来编译ndk程序。但是目前都是使用AndroidStudio做为开发和编译ndk的工具,因此我们关注AndroidStudio上的实现和编译。
zzyyppqq-超级简单的Android Studio jni 实现(无需命令行)
通过使用ndk提供的工具来编译ndk程序。
根据上述文档,总结一下开发ndk的流程以及编译过程:
1) public native String getString();在类中用native关键字声明一个成员方法 2) 调用javah程序,自动生成navtie方法对应的.h文件,得到可怕的c/c++函数原型: JNIEXPORT jstring JNICALL Java_com_zhangyp_higo_myndk_MyNdk_getString (JNIEnv *, jobject); 3) 在.c或.cpp文件中实现上面javah自动生成的函数 4) 编写mk文件,用于编译生成.so(类linux系统的动态链接库)文件 包括Application.mk和android.mk这两个mk文件 5) 你可以先调用一下ndk-build clear命令清理一下工程缓存之类的(有时不清理会出现一些问题),然后再调用ndk-build命令用于生成.so文件 6) 在android 类中使用static { System.loadLibrary("MyLibrary"); }方式,将刚才生成的.so加载进来,然后就按照正常的android开发流程进行native函数调用了。
由此可见,Ndk的开发也不是很难,只要记住上面几个步骤,就可以进行简单的ndk开发。
技术在发展,时代在进步。随着AndroidStudio的普及,引入了新的构建系统:gradle系统后,我们可以不用写.mk文件了 要知道,一个稍微复杂一点的ndk项目,要在.mk中撰写很多命令,单单.mk命令参考就有n多页,太可怕了!!
zzyyppqq-Android Studio使用gradle-experimental构建NDK工程(无需Android.mk、Application.mk文件)
1) gradle使用ndk编译,必须要使用:gradle-experimental 插件,这个需要到android相关网站去下载的 2) 一定要注意gradle-experimental的版本号与gradle的对应关系,不能搞混了。曾经我因为没注意这一点,导致掉在坑里两天没出来。太痛苦了(见下图说明)。 3) 一定要按照上文提到的步骤,一步步设置,zzyyppqq的gradle设置流程很清楚,就当武功口诀来使用,否则掉在坑里你也不知道怎么回事。 4) 代码的开发流程和.mk demo差不多,只是不需要编写.mk文件以及调用ndk-build命令了,这是使用gradle-experimental获得的最大好处。
再次强调一下:
gradle构建文档参考,请戳这里
1)需要在java类中用native声明方法 2)需要用Javah生成.h头文件 3)需要在实现.h中的函数时候,很熟悉java中的数据类型和c/c++中的数据类型之间的对应关系 例如JNIEnv,jobject,jstring等,还有其他很多数据类型,可以自己参看ndk开发文档。 4)需要有时调用如此长名字的函数:Java_com_zhangyp_higo_myndk_MyNdk_getString
有没有办法解决上面提到的那些问题呢?
………我们的猪脚…….SWIG库……出场了……
有了SWIG后,我们就可以正常方式编写C/C++代码,然后自动包装成ndk jni调用,不需要了解android ndk数据类型,不需要javah调用,也不需要native声明,Let’s go! go! go! go!
2、SWIG篇章:
SWIG全称是Simplified Wrapper and Interface Generator,官方网站是http://www.swig.org/。SWIG是一个开发工具,能够将使用C或者C++编写的软件与其他各种高级编程语言进行嵌入联接。
1)很简单,官网下载,解压到**最好没有中文字符的**文件夹下 2)由于要使用swig.exe命令行程序,最好设置一下环境变量 3) 在命令行中输入swig -help,出现各种命令参数,说明环境变量设置成功。
1) 严格按照zzyyppqq的文档配置好gradle以及gradle-experimental的参数 2) 在AndroidStudio中按zzyyppqq文档创建jni文件夹 3) 将用c/c++混合编程方式为ios/android实现一个自绘日期选择控件(一)中的 calendarCore.h和calendarCore.cpp文件复制到jni文件夹下面,如下图:
4) 编写swig.i文件(接口文件),用于描述如何输出.h文件为java接口,.i表示interface
5) 编写generate.bat文件用于调用swig.exe自动生成接口文件(很多个,具体我们图示)
双击运行bat前后效果如下:
6) swig转换的流程分析:
7) c/c++中的struct和class会自动生成java对应的类,并自动添加(如果需要的话)get/set函数:请查看CGPoint.java SCalendar.java等源码 8) c/c++中的输出参数,例如void calendar_get_year_month(SCalendar* calendar,int* year,int* month); int* year 和 int* month是传地址方式,将结果传出来,对于java来说,必须要装箱(boxing)以及拆箱(unboxing) 将int传值方式变为传引用方式,因此自动生成了SWIG_TYPE_p_int.java类,用于将值类型变为引用类型
3、 Android和ISO版Calendar的源码:
Android源码不再分析,实现细节可以参考
calendar IO实现
Android和IOS版所有的源码请狠狠地戳这里
https://github.com/jackyblf/
4、再次强调一下为什么用c/c++。基于虚拟机的源码实在太容易反编译了,c#/java/as3等代码,借助于一些工具,不到一分钟就可以将源码和资源全部反编译出来。大家可以下载一下微信android或faceu android版,反编译后发现,核心代码都在.so文件中,好多.so文件啊!
5、 到此,c/c++结合ios/android原生开发的文章结束了,花了两个礼拜,将近13000字。也算是呕心沥血吧。 如果觉得有用,请关注我一下,谢谢
说明:
关于一些原创的文章,除非是一些第三方经典源码分析,否则我一定会提供相应的demo。