JNI是什么?
JNI即 java native interface,是jdk里边的一部分属于java内容,主要确保java 与 native层(C/C++)通信。C/C++一般用于高效率的数学运算、游戏的实时渲染、音视频编码解码等。
此时需要通过jni进行转换。
例如:java层中的变量 String name = "王六";
Jni层 jstring name = "王六";
c/c++层 char * name = "王六";
Jni的调用类似java的反射调用。
签名规则
C/C++调用java类对象的属性/方法 的 签名规则
常用规则如下:
java类型----------属性类型符号
boolean----------Z
byte----------B
char----------C
short----------S
int----------I
long----------J
float----------F
double----------D
void----------V
object----------L完整的类名;
method(参数类型)返回值类型 ---------- "java": void name(int a,double b) "c++": (ID)V 其中(ID)表示入参的两个类型
可通过javap获取class文件的对应签名类型
android studio 开发jni开发
1、创建C++ 工程
2、导入C/C++文件
3、java/kotlin加载C/C++代码
调用规则
c++文件
native.cpp
#include <jni.h>
#include <string>
//extern "C" :下边的代码采用C的编译方式
//JNIEXPORT:JNI重要标记关键字,不能少(VS编译能通过,运行会报错) / (AS 运行不会报错), 规则(标记为该方法可以被外部调用) Windows内部规则,与Linux内部规则 不同
//jstring:代表 java 中的 String
//JNICALL : 也是一个关键字,(可以少的) jni call (约束函数入栈顺序,和堆栈内存清理的规则)
//jobject: java传递下来的对象,就是本项目中 MainActivity 对象
extern "C" JNIEXPORT jstring JNICALL
// 规则:
//Java_包名(以_连接,如果原包名中有下划线则表示1)_类名_方法名
Java_com_wangyb_c_1xiangxue_1project_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
// 如果是c文件 native-lib.c
//JNIEnv* env 是二级指针,使用时需要通过(*env)-> 调用
return env->NewStringUTF(hello.c_str());
}
//jclass :java传递下来的 class 对象,就是本项目中的 MainActivity class
extern "C" JNIEXPORT void JNICALL
Java_com_wangyb_c_1xiangxue_1project_MainActivity_changeName(JNIEnv* env,jobject obj) {
// 如果是c++文件 native-lib.cpp
//JNIEnv* env 是一级指针,使用时可直接调用env->,调用原理如下
// 1.修改name
jclass mainActivityCls = env->GetObjectClass(obj);
jfieldID name_fid = env->GetFieldID(mainActivityCls, "name","Ljava/lang/String;");
jstring value = env->NewStringUTF("李老八");
env->SetObjectField(obj, name_fid, value);
//如果在c中,c是没有对象的,想持有env环境必须传入进去
jstring value = (*env)->NewStringUTF(env,"李老八");
}
c文件
native.c
#include <jni.h>
//#include <string>
//extern "C" :下边的代码采用C的编译方式
//JNIEXPORT:JNI重要标记关键字,不能少(VS编译能通过,运行会报错) / (AS 运行不会报错), 规则(标记为该方法可以被外部调用) Windows内部规则,与Linux内部规则 不同
//jstring:代表 java 中的 String
//JNICALL : 也是一个关键字,(可以少的) jni call (约束函数入栈顺序,和堆栈内存清理的规则)
//jobject: java传递下来的对象,就是本项目中 MainActivity 对象
//extern "C"
JNIEXPORT jstring JNICALL
// 规则:
//Java_包名(以_连接,如果原包名中有下划线则表示1)_类名_方法名
Java_com_wangyb_c_1xiangxue_1project_MainActivity_stringFromJNI(
JNIEnv* env,
jobject obj) {
// std::string hello = "Hello from C++";
// 如果是c文件 native-lib.c
//JNIEnv* env 是二级指针,使用时需要通过(*env)-> 调用
return (*env)->NewStringUTF(env,"Hello from C++");
}
//jclass :java传递下来的 class 对象,就是本项目中的 MainActivity class
//extern "C"
JNIEXPORT void JNICALL
Java_com_wangyb_c_1xiangxue_1project_MainActivity_changeName(JNIEnv* env,jobject obj) {
// 如果是c++文件 native-lib.cpp
//JNIEnv* env 是一级指针,使用时可直接调用env->
// 1.修改name
jclass mainActivityCls = (*env)->GetObjectClass(env,obj);
jfieldID name_fid = (*env)->GetFieldID(env,mainActivityCls, "name","Ljava/lang/String;");
jstring value = (*env)->NewStringUTF(env,"李老八");
(*env)->SetObjectField(env,obj, name_fid, value);
}
原理
jni.h文件中
struct _JNIEnv;
struct _JavaVM;
typedef const struct JNINativeInterface* C_JNIEnv;
//此处表示是c++
#if defined(__cplusplus)
//JNIEnv是别名,所以JNIEnv* env是一级指针
typedef _JNIEnv JNIEnv;
typedef _JavaVM JavaVM;
#else
//此处表示c 。JNINativeInterface* JNIEnv是一个一级指针。所以JNIEnv* env是二级指针(形参 *xxx 已经是一个二级指针了),调用时需要(*env)
typedef const struct JNINativeInterface* JNIEnv;
typedef const struct JNIInvokeInterface* JavaVM;
#endif
struct _JNIEnv {
/* do not rename this; it does not seem to be entirely opaque */
const struct JNINativeInterface* functions;
查看 手机设备cpu架构 adb命令
adb shell getprop ro.product.cpu.abi