实际项目中的算法库很多是C++代码编写的,算法工程师经常面对的一个问题是算法的跨平台调用,比如算法工程师在平常工作中是基于C++代码进行算法开发的,公司开发一款android系统的应用程序,需要调用C++算法库,如何调用?解决这类问题的核心思想是:(一)跨平台编译工具CMake,即只需要一次编写算法代码,就可以在多个平台生成对应的算法库;(二)Android开发是基于java语言而算法库是C++代码实现的,我们面对的另一个问题是在android开发中用java语言调用C语言算法接口,不同语言有不同的书写规范,这当然是不可能编译成功的,因此我们需要通过中间层(JNI编程)来搭建java语言和C语言沟通的桥梁,本文就通过android系统调用C++算法库来阐述算法库的跨平台调用思想(文末附完整代码链接)。
目的:Android开发调用C++算法库(数组求和算法)
Android集成开发工具:Android Studio3.10.2
跨平台编译工具:CMake3.4.1
1. 新建使用JNI编程的工程
1)File -> New -> Project,勾选native C++,表示项目中可使用C语言进行编码。
2)设置项目和包的名称:
在向导的Customize C++ Support部分,选择默认的Toolchain Default。
2. 下载JNI开发所需的NDK,LLDB,CMake工具包
1) 打开Android studio -> Preferences -> Android SDK;
2) 在SKD标签中选择LLDB,NDK,CMake工具包进行下载;
JNI:Java Native Interface(Java本地编程接口),一套编程规范,它提供了若干的API,实现了Java和其他语言的通信(主要是C/C++)。
NDK:Native Development Kit(本地开发工具),一系列工具的集合,这套工具允许你在Android开发中使用C和C++代码。
CMake:跨平台编译工具。
LLDB:一种调试程序,ANDROID STUDIO使用它来调试原生代码。
3. 切换到project选项,在目录 jniarray/app/src/main/java的Mainactivity.java中写求向量求和算法的接口函数:
我们只声明了接口函数并无实现,因此接口函数显示红色的。
同时按option键+enter键,选择create function Java_com_zl_jniarray_MainActivity_sumArray并按Enter键,在nativa-lib.cpp生成该接口函数的实现体:
下面编码该接口函数的实现:
细心的读者会发现该接口函数的实现与cpp并不完全相同,如jint表示整型变量,jintArray表示整形数组,因为接口函数是通过JNI编码实现的,JNI与java语言和C语言都能进行交互。
我们完成了接口函数的实现后,用CMake进行编译,生成Android开发所需要的算法库,CMakeList.txt文件是指定CMake的编译规则,下面解释下该项目的编译规则:
4 .点击项目构建按钮
默认生成的库路径为:app/build/intermediates/cmake/debug/obj/
实际开发中需要release模式下的算法库,我们在Android Studio左下角点击Build Variants标签并选择Release-x86,再次重新构建生成release模式下的动态库:
生成release模式下的动态库:
5. jar包的生成
Android开发以.so库和jar包的形式调用算法库,我们已经生成了debug和release模式下的.so动态库,下面介绍如何生成jar包。
切换为Android选项:
新建模块module,选择Android Library
点击下一步,设置module的包名应和app的包名相一致:
在目录com.zl.jniarray新建java类,该类名与app的类名相同,声明接口函数,并下载算法库:
在jniarray中的build.gradle文件添加下面语句,目的是设置保存jar文件的路径和重新命名jar文件:
重新编译,切换目录为jniArray文件夹,使用如下命令./gradlew makeJar重新命名jar文件。
因此,我们在jniarray/build/libs文件夹生成jni-array的jar包。
6. 算法测试
新建工程,选择empty activity,其他选项默认,点击Finish。
在目录MyApplication2/app/lib文件夹添加算法.so库和jar包:
添加jar包到该项目中,右键jni-array,点击Add As Library。
则会在app的gradle文件中自动添加下面的语句:
在app的gradle文件中添加搜寻动态.so库的路径:
我们在com.zl.myapplication包中的MainActivity1.java中成功调用了C++算法库。
6. 后续说明
这只是一个简单的Android开发调用C++库的例子,实际项目的算法远远比这个复杂,但是思想其实是不变的,因为我们有了CMake这个强大的工具,只要我们写了算法的cpp文件,然后复制粘贴到cpp和header文件夹内,写好你的CMakelist配置文件,就能生成跨平台库了,当然,项目自带的非算法cpp文件包含了JNI编程,它是沟通算法库与java语言的桥梁,我们用java语言调用JNI编程的接口函数,然后JNI调用C++算法,JNI也成为中间层。
调用流程:
JNI编程最大的难点之一是类型的转换和方法的调用,这里我就不展开了,若有问题的话可以私信小编。
如下图的项目算法的文件说明,红色框的文件是我已经写好的算法文件,蓝色框是JNI编程,算法文件复制粘贴到cpp文件夹即可,我只需要写蓝色框文件的接口函数,目标是实现java语言调用C++代码的算法库。
7. 小结
文章通过简单的例子说明了java语言调用c++库的过程,这种跨平台调用算法库的思想是算法工程应掌握的,希望这篇文章能够帮到你。
完整代码链接:
github:https://github.com/zhangleiszu/Android-C-
欢迎扫码关注: