一、Jni简介
Jni全称是java Native Interface(Java本地接口),它是java平台的一部分,允许Java代码和其他语言编写的代码进行交互,它使得在Java虚拟机(JVM)内部运行的Java代码可以和其他语言编写的应用程序或库进行交互操作。
二、hello-jni项目简介
截图如下:
这里先对各个文件夹进行分析:
1、jni文件夹
要想在Java项目里或是Android项目里面调用native代码必须在项目下面新建一个jni目录,在这个目录里面编写有关native代码,并且编写编译规则(Android.mk文件),这里重点细说一下这个文件~
这个文件主要是规定编译器如何去生成.so文件、引用的头文件目录、需要编译的.c .cpp .a等文件,hello-jni里面的Android.mk文件很简单并且只有一个,所以先简单分析一下hello-jni提供的Android.mk文件~
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := hello-jniLOCAL_SRC_FILES := hello-jni.cinclude $(BUILD_SHARED_LIBRARY)LOCAL_PATH := $(call my-dir)
LOCAL_PATH这个变量用于给定当前文件的路径,my-dir这个宏是由Build System提供的,用于指出当前文件夹所在的路径。
include $(CLEAR_VARS)
这个include的作用就是指向一个编译脚本,指向哪个脚本由括号内的变量决定,CLEAR_VARS指向了一个清理以LOCAL_开头的变量(LOCAL_PATH这个变量排除在外,因为每个模块都会用到当前文件的路径)。在Android.mk中可能会存在很多的模块,每个模块都会有一些变量,而且这些变量又都是全局的,Build System每次只能编译一个模块,所以在每一个模块的最开始都要执行CLEAR_VARS这个脚本来清理其他模块的变量。
LOCAL_MODULE :=hello-jni
这个变量是规定Android.mk文件执行完成之后生成的so文件的名字,在生成so文件的过程中Build System会自动加上lib和.so后缀,比如这个,最后会生成libhello-jni.so这个文件,这个文件可以再代码里面加载,代码如下:
/* this is used to load the 'hello-jni' library on application * startup. The library has already been unpacked into * /data/data/com.example.hellojni/lib/libhello-jni.so at * installation time by the package manager. */ static { System.loadLibrary("hello-jni"); }LOCAL_SRC_FILES :=hello-jni.c这个变量规定要打包的Native的源码,如示例中的hello-jni.c,这里不需要列出头文件,因为Build System会自动加载头文件的,缺省的C++扩展名为cpp,要想改变C++的扩展名,修改LOCAL_CPP_EXTENSION就可以了。
include $(BUILD_SHARED_LIBRARY)
这个BUILD_SHARED_LIBRARY是由Build System提供的一个变量,指向一个编译脚本,用来收集上一次执行CLEAR_VARS这个脚本之后所有的LOCAL信息,并且决定编译生成什么类型的文件。
BUILD_SHARED_LIBRARY 编译为动态库
BUILD_STATIC_LIBRARY 编译为静态库
BUILD_EXECUTABLE 编译为Native程序
这个hello-jni的Android.mk文件就说完了~
Application.mk:这个文件是描述你的应用程序中所需要的模块(静态库还是动态库)
APP_ABI :=all 这个表示编译出所有平台。
我们知道,这个ABI表示ApplicationBinaryInterface(应用程序二进制接口),一个应用程序一般是由高级语言编写完成之后,经过编译生成汇编程序,然后在链接生成二进制文件,这个生成二进制文件的过程中有一个ABI的概念,决定了生成的二进制程序可以运行在哪个CPU架构上(也就是不同的平台)
这个Application.mk文件就说完了~
hello-jni.c文件是Native源码文件
/* * Copyright (C) 2009 The Android Open Source PRoject * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */#include <string.h>#include <jni.h>/* This is a trivial JNI example where we use a native method * to return a new VM String. See the corresponding Java source * file located at: * * apps/samples/hello-jni/project/src/com/example/hellojni/HelloJni.java */jstringJava_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env, jobject thiz ){#if defined(__arm__) #if defined(__ARM_ARCH_7A__) #if defined(__ARM_NEON__) #if defined(__ARM_PCS_VFP) #define ABI "armeabi-v7a/NEON (hard-float)" #else #define ABI "armeabi-v7a/NEON" #endif #else #if defined(__ARM_PCS_VFP) #define ABI "armeabi-v7a (hard-float)" #else #define ABI "armeabi-v7a" #endif #endif #else #define ABI "armeabi" #endif#elif defined(__i386__) #define ABI "x86"#elif defined(__x86_64__) #define ABI "x86_64"#elif defined(__mips64) /* mips64el-* toolchain defines __mips__ too */ #define ABI "mips64"#elif defined(__mips__) #define ABI "mips"#elif defined(__aarch64__) #define ABI "arm64-v8a"#else #define ABI "unknown"#endif return (*env)->NewStringUTF(env, "Hello from JNI ! Compiled with ABI " ABI ".");}这个源文件的编写和普通的C文件不太一样,因为是和Java打交道的嘛~这个jstring是jvm里面的字符串,下面是Java和C++的类型在JVM里面的映射:
函数名称之所以要这么写是因为要和调用这个函数的java代码交互,截图如下:
Java是固定的,com_example_hellojni这个是包名,HelloJni这个是类名,stringFromJNI这个就是Java的native方法了~
这个说完了函数名称编写,然后看一下这个函数的参数
第一个JNIEnv类型的参数,通过这个参数我们可以在Native代码里面获取一些Java代码的信息。我们在Java端的函数是没有这个参数的,这个参数是从Java端自动传过来的,作用是提供给JNI一个Java的运行环境,在Java里面就是JVM,在Android里面就是Dalvik VM。
第二个jobject类型的参数的意思是,如果这个Native方法是静态的话,jobject表示的就是这个包含这个Native方法的类的实例,如果这个Native方法不是静态的话,jobject表示的就是这个类的对象的实例。
hello-jni.c就到这里了。
有什么疑问可以加我QQ:763949771,一起交流学习。如有错误请留言指正~
新闻热点
疑难解答