IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> JNI开发笔记(四)--实现一个简单的JNI工程并生成so库 -> 正文阅读

[移动开发]JNI开发笔记(四)--实现一个简单的JNI工程并生成so库

JNI开发笔记(一)–Android Studio安装与环境搭建
JNI开发笔记(二)–创建JNI基础工程并运行
JNI开发笔记(三)–JNI工程的框架分析

前言

本篇文章根据Android Studio自带的JNI工程模板,添加一些简单的C/H函数来实现一个简单的JNI工程。以简单的两数相加为例,将C语言实现的sum函数通过JNI由Java来调用。

1. 编写C/h文件并添加到工程

首先我们实现两数相加,由于比较简单,直接上代码就好:

// sum.c
int sum(int x, int y){
	return x + y;
}
//sum.h
#ifndef __SUM_H__
#define __SUM_H__

int sum(int x, int y);

#endif

然后我们将sum.c和sum.h添加到工程中,具体的步骤是:

  • 将两个文件复制
  • 打开JNI基础工程,选中CMakeLists.txt所在的文件(单击CMakeLists.txt选中,如下图所示),然后粘贴即可
    在这里插入图片描述
    这样sum.c和sum.h就添加到了我们的JNI工程中。

2. 修改CmakeLists.txt文件

根据JNI开发笔记(三),我们针对CmakeLists.txt只需要修改三个地方就可以了,代码如下:

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.10.2)

# Declares and names the project.

project("test")

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
             JniTest-lib  //第一个修改的地方,更改so库的名字

             # Sets the library as a shared library.
             SHARED    //第二个部分,我们需要把相关的c/h文件加到下面
             sum.h
             sum.c

             # Provides a relative path to your source file(s).
             native-lib.cpp )

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
              log-lib

              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
                       JniTest-lib  //第三个部分,这个名字要和上面的名字一致

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )

3. 编写native-lib.cpp文件

native-lib.cpp文件的作用是将C文件中的sum函数封装成Java可以识别的函数。首先我们需要在MainActivity.java中声明一个Java的函数名,

public native int sumfunc(int x, int y);

如下图所示,我们在红色矩形框的地方声明该函数:
在这里插入图片描述
可以发现这个函数名“sumfunc”变红了,那是因为Java没有找到和这个函数名匹配的函数。我们把鼠标移动到这个红色的函数名字上,然后Android Studio会出现一个错误提示,说找不到对应的JNI函数,如下图所示。提示的左下角会出现一个“Create JNI function for sumfunc”, 然后我们点击这个蓝色字体,页面会自动跳到native-lib.cpp中,并帮我们建立好对应函数名的函数体。

在这里插入图片描述
自动建立的sumfunc函数体如下图所示

在这里插入图片描述
函数名是Java识别JNI函数的标志,所以比较长,前面要添加包名和声明函数所在文件的名称,这也是为什么我们选择“Create JNI function for sumfunc”来建函数的原因,因为自己手动创建容易出错。在我们的工程中,函数名为:

Java_com_jni_test_MainActivity_sumfunc(JNIEnv *env, jobject thiz, jint x, jint y);

其中函数参数的意义如下:

  • “JNIEnv *env” 定义了一个与JNI语法相关的指针变量,通过env这个指针我们可以很方便的调用关于JNI的一些语法,这个我们目前用不到,后面遇到env的时候大家就知道怎么回事了。
  • jobject thiz 参数将是对MainActivity类型的对象的引用,该参数在JNI开发中基本用不到,我们可以暂时忽略
  • jint x, jint y: 前两个参数(env和thiz)是每一个JNI的函数都会带有的变量,后面的x,y才是我们传入的参数,“jint” 表示的就是int型变量,前面的“j”表示JNI的意思,同样的,jflloat表示float, jshort 表示short, jdouble表示double。这涉及到JNI的语法,我们后见会详细讲解。

我们需要在这个函数下完成对C文件中sum函数的封装,首先需要引入sum.c所依赖的头文件sum.h,我们在native-lib.cpp中添加sum.h, 添加“extern "C"表示以C语言的方式引用头文件:

在这里插入图片描述
然后在“Java_com_jni_test_MainActivity_sumfunc”函数中就可以直接引用sum.c中的sum函数了:

在这里插入图片描述
这样我们的native-lib.cpp就修改好了, 现在这个形式的函数可以被Java识别到,然后Java端传参数x,y进来,我们在函数内部可以运行C函数sum(x ,y)将二个参数相加并返回结果。

4. 在MainActivity.java文件调用C函数

在Java中怎么实现传参数给我们的JNI函数呢?我们通过MainActivity.java来实现。打开MainActivity.java,我们需要修改两个地方,第一个是将导入的库名字改成我们在CMakeLists中的名字“JniTest-lib”, 第二个地方是在tv.setText()中直接引用我们的函数:

tv.setText(String.valueof(sumfunc(1, 2)));

因为sumfunc返回时int型变量,所以需要使用String.valueof()来变成字符型才能显示出来。

在这里插入图片描述
也就是说,只要正确引入了JNI对应的library,我们可以直接使用library中的JNI函数。

5. 运行JNI工程

我们点击左上角的三角形“run”按钮,可以运行这个简单的JNI工程了。

在这里插入图片描述
运行完毕之后我们可以在虚拟安卓机上看运行的结果了:
在这里插入图片描述

这样一个简单的JNI工程就运行成功了,它实现了通过Java来调用C文件中的sum函数并返回到Java中的功能。

6. 生成so库

如果我们要给其他java程序调用我们的sum函数,但是不想暴漏sum里面的实现细节,我们需要把我们的JNI工程打包成一个so库,操作非常简单,点开右侧的“Gradle”,找到路径“JniTestProject–Tasks–build”,双击“assemble”进行so库的生成。

在这里插入图片描述

assemble完毕之后,点击左上角的“Android”图标,切换当前工程环境为“Project”

在这里插入图片描述
在我们的工程下“JniTesetProject–build–intermediates–cmake”中
在这里插入图片描述
我们可以找到对应各个平台的so库文件了:

在这里插入图片描述

多说一句

我们在平时开发中会遇到比这个复杂的多的场景,比如我们C语言接口函数的参数是变量指针的时候该怎么转化,是数组指针该怎么转化,结构体指针呢?这些场景就需要使用特定的JNI语法来进行转化。针对这样复杂的问题我在下一篇文章JNI开发笔记(五)中会专门讲解。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-12-23 15:51:56  更:2021-12-23 15:53:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 10:41:36-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码