1 编写native方法
public class JniTest {
public native static String getStringFromC();
public static void main(String[] args) {
}
}
2 javah命令,生成.h头文件
1在src上右键然后选properties,然后选择拷贝
2打开cmd命令 cd到刚才的src目录下。
3 使用javah命令,并拷贝全类名
4 会提示找不到什么的类文件
这时需要在javah 后添加-jni。如果还是不行,那就添加classpath . 注意这里有个点。这样就可以了。
并可以看到.h的头文件
3 复制.h头文件到cpp工程
1 把之前生成的.h文件复制到cpp工程中
2 在cpp工程右键选择添加现有项
通过这样把刚才拷贝到工程中的.h文件添加到本工程中。
添加过来后会发现报红
4 复制jni.h和jni_md.h
用同样的方式把jni.h也添加到工程中
把尖括号改成双引号
最后用同样的方式把jni_md.h也添加过来。这样就不报错了
5 实现.h文件中的函数
#include "com_yeliang_JniTest.h"
//函数实现
JNIEXPORT jstring JNICALL Java_com_yeliang_JniTest_getStringFromC(JNIEnv *env, jclass jcss){
//将C的字符串转为一个java字符串
(*env)->NewStringUTF(env,"C String");
}
6 生成dll动态文件
选中上面的源文件,右键选择属性 然后选则配置管理器 选择平台为X64
选中项目然后右键,选择属性,把配置类型改为动态库
运行后会看到生成的dll动态库
7 通过java调用C
1 加载动态库
static{
System.loadLibrary("jni_study");
}
2 配置dll文件所在目录到环境变量
或者通过直接把dll文件考到工程的根目录下。都可以加载到动态库的文件。
然后重启eclipse,因为新增加了环境变量。
3 调用native方法
public class JniTest {
public native static String getStringFromC();
public static void main(String[] args) {
String text = getStringFromC();
System.out.println(text);
}
//加载动态库
static{
System.loadLibrary("jni_study");
}
}
打印结果
C String
整个过程就是在Java中会有一个native的方法,并加载了dll的动态库。java类会在动态库中找这个方法(方法名为:java_完整类名_函数名)。
可以看出C的函数名为:Java_完整类名_函数名
JNIEnv 相关解释
1 在C中JNIEnv是结构体指针
代表Jav运行环境。调用java中的代码。
转到声明后可以看到:
typedef const struct JNINativeInterface_ *JNIEnv;
在转到定义后可以看到
struct JNINativeInterface_ {
void *reserved0;
void *reserved1;
void *reserved2;
void *reserved3;
jint (JNICALL *GetVersion)(JNIEnv *env);
jclass (JNICALL *DefineClass)
(JNIEnv *env, const char *name, jobject loader, const jbyte *buf,
jsize len);
jclass (JNICALL *FindClass)
(JNIEnv *env, const char *name);
都是去调用java中的方法。并且可以看出env是一个二级指针。
2 在cpp中JNIEnv就是一个结构体别名
通过转到定义后可以看到。
#ifdef __cplusplus //如果是定义的cpp
typedef JNIEnv_ JNIEnv; //结构体
#else //如果是定义的c
typedef const struct JNINativeInterface_ *JNIEnv; //结构体的指针
#endif
env 在c++中是一个结构体的一级指针
总结
JNI(Java Native Interface)
Java调用C/C++,C/C++调用java的一套API。
提升效率 保证代码安全
.a静态库 全部都会包含在最终生的的exe文件里面。
.dll动态库 共享代码的方式。