Android平台调用c++

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android平台调用c++相关的知识,希望对你有一定的参考价值。

小白:java代码中,为什么不能直接写c或c++代码?而oc代码却可以直接写!

小程:你可以写,只是编译不过而已。

小白:那不就是不能写嘛!

不管是编译到jvm,还是dalvik上运行,java的编译器都不会直接生成执行文件,而只是生成字节码(表现为class文件,或者是经过转换的dex文件),这跟c/c++编译器的做法大为不同,而很可能因为这个原因,使得java中不能参杂c/c++代码,而objective-c就可以混编c/c++,因为它的编译器直接生成执行文件。

那java语言就不能使用c++代码了吗?有问题,就有解决办法,办法是使用JNI。

JNI(java native interface,即java本地接口)的出现,可以解决java与c++交互的问题,并且不仅限于c++。

小白:可是,我的android程序,为什么要调用c++的代码呢?

小程:事出有因,比如已经实现某个功能的是c++代码而非java代码,比如要进行大量的数据运算而c++的执行性能远在java之上,比如要调用一些驱动类的接口,比如...

本文演示java如何调用c++的代码,即jni的使用。

jni层,可以分为jni上层,跟jni下层。

jni上层用java实现,jni下层用c/c++实现。

大概的调用关系是这样的:
技术分享图片

小程接下具体介绍jni上下层的实现,并介绍如何生成so库(so库代表了c++实现的功能)并调用它。

(1)实现jni上层

随便找一个java类(或者新建一个),然后在里面声明一个native方法,就实现了jni上层。

比如,创建一个Android Studio项目,并且有这样的native方法声明:
技术分享图片

至此,就已经建立了jni上层。

(2)实现jni下层

java代码调用jni上层的native函数时,会调用到c++的什么函数?这里需要有映射的关系。

建立起这个映射,有两个办法。

办法一:使用签名

对于native方法,使用javah,可以抽取出对应的签名,然后c++实现这个签名的函数即可。

可以这样生成签名:
技术分享图片

这个.h文件的内容是这样的:
技术分享图片

那一长串就是对应的签名,c++代码实现这个函数,这样java在调用jni上层声明的native函数时,就会调用到这里面来。显然,一旦建立了映射,jni上层与下层就不能再改名字(除非重新签名)。

小白:一大串的,还不给改名,大不人性化了。

小程:要改名就新增接口吧,或者,使用第二个办法。

办法二:使用RegisterNatives

在jni层加载时,调用RegisterNatives。

这种办法,没有使用javah生成固定的签名,而是使用RegisterNatives来建立navtive方法与具体的实现的关联,具体实现可随意命名。

在JNI_onLoad函数内,触发RegisterNatives的调用:
技术分享图片
技术分享图片

在解决掉jni上下层的映射问题后,就是natvie方法的具体实现了。这里介绍如何生成动态链接so库。

在项目的根目录中,创建一个jni目录,在里面写c/c++代码与编译脚本,目录结构是这样的:
技术分享图片

impl.c的内容:
技术分享图片

脚本Android.mk的内容:
技术分享图片

执行ndk-build,生成so库:
技术分享图片
技术分享图片

可以用readelf查看so库:
技术分享图片

这里涉及到编译脚本(Android.mk)的规则、smalis语言特征(jni的数据类型等),还有ndk-build的使用等知识,小程不展开了,读者可以关注“广州小程”微信公众号,并获取后续的更新。

(3)调用jni层

在java层调用native方法,比如:
技术分享图片

执行这个程序,可以看到输出:
技术分享图片

到此,如何在Android平台调用c++的实现就介绍完毕了。


总结一下,本文介绍了如何在Android平台调用c++的实现,演示了jni层的创建与编译出so库,并且调用了so库。读者可以把这部分知识应用到实际的Android项目中。

以上是关于Android平台调用c++的主要内容,如果未能解决你的问题,请参考以下文章

Android平台Native开发与JNI机制详解

Unity 使用C/C++ 跨平台终极解决方式(PC,iOS,Android,以及支持C/C++的平台)

Android .so

研发干货丨基于OK3399-C平台android系统下实现图像识别

Android JNI编程—JNI基础

Android 平台上的原生 C/C++ 代码