JNI程序编写与简单分析

环境准备:


建立JNI项目:

上图中的Toolchain工具集就是由NDK包提供的一部分类,所以NDK是必须要安装的。

默认即可。如果上面的环境准备没有做的话,直接新建jni项目也是会有Gradle提示你安装的。


生成目录如下:


大致分析demo:

MainActivity做的第一件事:将要用的c++库先导入进来,这样我们才能调用这个库里面的c++方法.如果这个库不在内存中, 我们是没法调用的。

有了库之后。它调了一个方法:

来,我们瞅瞅这函数和我们android开发中常写的函数有何不同:

哦~~一般的函数没有native字样。为了调c/c++相关的方法的时候要标识native。也就是说,这个方法是由C/C++提供的,即这是一个本地方法,要加上一个标识。这样Java/kotlin就能知道要到系统的库里

System.loadLibrary("native-lib");

提供的这个库里去找相应的方法。

 

第二个不同的是:

因为现在最新的版本用的CMake进行编译.

以前这个不叫cpp目录,叫jni,现在新版androidstudio改成了cpp

关于CMakeLists.txt是CMake的东西,可以参考这篇老哥的文章:https://www.cnblogs.com/sddai/p/10328977.html

文末写了关于CMakeLists文件内容的分析。

然后看看native-lib.cpp:[典型的c++文件]

规律:包名_类名_方法名

这个名字可以自己创建,也可以通过javah工具产生。如果你对名字特别熟悉也可以自己写。

这样的一个命名规则 ,Java虚拟机就可以找到这个cpp方法.也就是说刚刚在mainactivity中的native函数

stringFromJNI. 它属于Java包下的。

通过这样去查找就可以在java虚拟机里去找到对应的c方法。。

再看这个c方法:“

这个方法并没有做什么事,就是生成了一个字符串。然后把这个字符串返回回去。

拿到这个方法过后,就把这个字符串从c层转化到了java层.然后java层拿到这个方法后就得到了字符串,然后设置给了TextView了。

所以,等会运行的时候,我们应该是能看到app启动后显示Hello from C++

来,让我们运行验证下我们的猜想:


使用JNI的时候总结:

  1. loadLibrary
  2. 实现相应的c层方法
  3. CMake,产生编译脚本。【CMakeLists.txt就可以产生编译脚本】

CMakeLists.txt是啥?

 

通过这个CMakeLists.txt就可以产生编译脚本。

CMakeLists实际上是给CMake使用的.CMake会通过CMakeLists去产生我们想要的编译脚本.在CMakeLists里有几个指令。

先看这个指令:

这个指令叫add_library,这指令的作用有2方面的作用,第一方面可以根据我们的c文件产生一个动态库,其中产生的是动态库还是静态库由第二个属性决定,即我们这里看到的SHARED。我们的库的名字叫做native-lib,它是一个动态库SHARED,如果是静态库就是STATIC.

这个动态库是由native-lib.cpp产生的。【其实CMakeLists.txt文件里面的英文注释已经写的很清楚了。】

即这个指令就是产生一个动态库。

如果您的库还需要依赖于其他的库,那么就看看这个指令:

通过这个指令去查找系统的库,那么这个系统的库必须是在CMake指定的路径下,像这里的log就在系统的库下。并起了个名字log-lib。

再看下一个指令:

通过这个名字就知道是链接的意思。即之前addlibrary指令找到的库和find_library指令找到的log库,将这2个库链接到一起最终形成一个库。怎么链接——通过target_link_libraries指令。将谁链接起来了,就是将上图中看到的native-lib和log-lib把这2个库链接到一起。

如果这里我有第3 个库,要将第3个库链接,就直接在后面加上xxx

还有一个额外问题:如果我们想要添加一个库,这个库并不在系统的CMake能找到的默认路径下,这怎么办才能引入呢?

add_library。给库起名字,指定共享库还是静态库, import在别的地方已经编译好的这个库引入。

编译FFmpeg好的库也是通过这个指令从外部引入进来的。

 


学习JNI的基础知识路线:

学习jni、FFmpeg等需要先掌握JNI的基础知识,

  • JNI_C 语言基本类型
  • 输出函数
  • 输入函数
  • 指针【认识与深入理解】
  • 在单独方法中互换地址
  • 函数返回一个以上的值
  • 多级指针
  • 数据
  • 输入数组
  • 数组的取值运算
  • 静态内存分配
  • 动态内存分配
  • 动态创建数组
  • 函数指针
  • 联合体
  • 枚举
  • 结构体
  • 结构体指针
  • Java调用C代码执行运算
  • c调用Java方法返回值
  • 让c的输出能显示在Logcat中
  • c调用java方法(String参数)
  • c调用java(回调静态方法)

。。。。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章