示例JNI加减乘除

    xiaoxiao2022-07-05  139

    前言

    JNI是JavaApp与Native Libs沟通的桥梁:Android 平台从一开就已经支持了C/C++了。我们知道Android的SDK主要是基于Java的,所以导致了在用Android SDK进行开发的工程师们都必须使用Java语言。不过,Google从一开始就说明Android也支持JNI编程方式,也就是第三方应用完成可以通过JNI调用自己的C动态度。于是NDK就应运而生了:

    1. 配置环境

    app的build.gradle配置指定native的编译脚本的位置 android { ... externalNativeBuild { cmake { path "src/main/cpp/CMakeLists.txt" version "3.10.2" } } }

    C++的make文件加载的c文件为:native-lib.cpp, lib起名字为“native-lib”

    cmake_minimum_required(VERSION 3.4.1) add_library( # Sets the name of the library. native-lib # Sets the library as a shared library. SHARED # Provides a relative path to your source file(s). native-lib.cpp ) ...

    2. 编写C++文件

    cpp文件编写,定义了几个方法:加减乘除等

    #include <jni.h> #include <string> extern "C" JNIEXPORT jstring JNICALL Java_com_linx_jnitest_JNILoader_GetNativeString(JNIEnv* env, jobject thiz) { return (jstring)env->NewStringUTF("hello from jni"); } extern "C" JNIEXPORT jint JNICALL Java_com_linx_jnitest_JNILoader_Add(JNIEnv* env, jobject thiz, jdouble num1, jdouble num2) { return (jint)(num1 + num2); } extern "C" JNIEXPORT jint JNICALL Java_com_linx_jnitest_JNILoader_Sub(JNIEnv* env, jobject thiz, jfloat num1, jfloat num2) { return (jint)(num1 - num2); } extern "C" JNIEXPORT jint JNICALL Java_com_linx_jnitest_JNILoader_Mul(JNIEnv* env, jobject thiz, jlong num1, jchar num2) { return (jint)(num1 * num2); } extern "C" JNIEXPORT jint JNICALL Java_com_linx_jnitest_JNILoader_Div(JNIEnv* env, jobject thiz, jint num1, jint num2) { return (jint)(num1 / num2); }

    静态加载JNI library,编译脚本中定义的lib名字;并定义对应的native方法,方法名称首字母大写,参数类型对应;

    public class JNILoader { static { System.loadLibrary("native-lib"); } public static native String GetNativeString(); public static native int Add(double num1, double num2); public static native int Sub(float num1, float num2); public static native int Mul(long num1, char chart); public static native int Div(int num1, int num2); } public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Example of a call to a native method TextView tv = findViewById(R.id.sample_text); tv.setText(JNILoader.GetNativeString()); TextView tv1 = findViewById(R.id.tv1); tv1.setText("add="+ JNILoader.Add(5.7, 3.5)); TextView tv2 = findViewById(R.id.tv2); tv2.setText("sub="+ JNILoader.Sub(2.8f, 1f)); TextView tv3 = findViewById(R.id.tv3); tv3.setText("mul="+ JNILoader.Mul(1l, 'a')); TextView tv4 = findViewById(R.id.tv4); tv4.setText("div="+ JNILoader.Div(5, 2)); } }

    结果如下:

    总结

    c++文件的方法编写方式遵循特定的语法: 与明确加载library的java文件名称相关:Java_[包名]_[加载类Java类名称]_[方法名称],例如:Java_com_linx_jnitest_JNILoader_GetNativeString对外公开的方法开头:extern "C"返回类型:JNIEXPORT [返回类型]方法声明参数和返回类型必须是JNI定义的类型:jint、jfloat、jchar、jstring、jdouble、jlong…等等,其他的函数或方法体内部可以完全使用c语言规范编写;特别注意:native方法都是大写字母开头,c中的方法也是大写开头; JNI是java native 方法与 c方法沟通的桥梁,通过将c语言类型转换为jint/jdouble等类型,就可以与java类型映射,达到跨平台调用的目的

    NDK使用场景

    Android NDK 就是一套工具集合,允许你使用C/C++语言来实现应用程序的部分功能。

    1、在平台之间移植其应用2、重复使用现在库,或者提供其自己的库重复使用3、在某些情况下提高性能,特别是像游戏这种计算密集型应用4、使用第三方库,现在许多第三方库都是由C/C++库编写的,比如Ffmpeg这样库。5、不依赖于Dalvik Java虚拟机的设计6、代码的保护。由于APK的Java层代码很容易被反编译,而C/C++库反编译难度大。
    最新回复(0)