JNI(Java Native Interface)Java本地化接口,Java调用C/C++,C/C++调用Java的一套API接口
实现步骤
在Java源文件中编写native方法
1
public native static String getStringFromC();
到Java源代码src路径下,使用
javah
命令生成.h
头文件
注意:此处的参数为包名+类名1
2//生成的头文件为:com_cj5785_jni_JniTest.h
javah com.cj5785.jni.JniTest复制.h头文件到CPP工程中,修改文件包含
1
2//生成的C函数名:Java_完整类名_函数名
复制jni.h和jni_md.h文件到CPP工程中
jni.h和jni_md.h位于Java安装目录下实现.h头文件中声明的函数
1
2
3
4
5
6
7
8
9//为与头文件相匹配,此时将实现文件取名为:com_cj5785_jni_JniTest.c
//函数实现
JNIEXPORT jstring JNICALL Java_com_cj5785_jni_JniTest_getStringFromC
(JNIEnv *env, jclass jcls)
{
//将C的字符串转换为Java的字符串
return (*env)->NewStringUTF(env, "C String");
}生成dll文件,供Java调用
Debug -> 平台(x64) -> 确定
项目(右键) -> 属性 -> 配置属性 -> 常规 -> 生成dll动态库将生成的dll文件放在Java的src目录同级下,加载动态库
1
2
3static{
System.loadLibrary("");
}
整个java项目文件源代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17package com.cj5785.jni;
public class JniTest {
static {
System.loadLibrary("JNITest");
}
public native static String getStringFromC();
public static void main(String[] args) {
String str = getStringFromC();
System.out.println(str);
}
}
运行以后在控制台输出:C String
在生成的dll过程中,会生成在相应配置的目录下
JNI说明
JNIEnv与env
JNIEnv:结构体指针
env:二级指针
JNIEnv代表Java运行环境,调用Java中的代码
在C中
JNIEnv:结构体指针别名
env:二级指针在C++中
JNIEnv:一个结构体指针的别名
env:一级指针为何需要传入JNIEnv?
C函数执行过程中需要JNIEnv- C++为何没有传入?
C++中有this指针,可以拿到当前指针,对C语言而言,要修改指针的值,只能通过二级指针 - C++对C进行封装,给一个变量赋值为指针,这个变量就是二级指针
1
2
3
4
5
6
7struct JNINativeInterface_;
struct JNIEnv_;
typedef JNIEnv_ JNIEnv;
typedef const struct JNINativeInterface_ *JNIEnv;
jclass说明
jclass代表native方法所属类的class对象,这里代表了JniTest.class
C与C++的实现
在函数实现的时候是不一样的
c实现:1
2
3
4
5
6
JNIEXPORT jstring JNICALL Java_com_cj5785_jni_JniTest_getStringFromC
(JNIEnv *env, jclass jcls)
{
return (*env)->NewStringUTF(env, "C String");
}
C++实现1
2
3
4
5JNIEXPORT jstring JNICALL Java_com_cj5785_jni_JniTest_getStringFromC
(JNIEnv *env, jclass jcls)
{
return env->NewStringUTF("C String");
}
JNIEnv实现模拟
1 | //JNIEnv结构体的指针别名 |