1.之前有分享过简单的使用JNI: https://blog.csdn.net/m0_37874087/article/details/80311762
2.熟悉了JNI的使用,我们肯定有点不爽的是:
- javah 自动生成文件名是又臭又丑;
- 而且在实际项目中,总不能添加一个函数,就去重新生成一把,我们最喜欢的是改动最小使用最方便。
3.现在我们就来11解决
要使用我们自己命名的.C/.CPP文档,当然就是要实现它的实现过程:
jint JNI_OnLoad(JavaVM *vm, void *reserved); //vm: a pointer to the current VM structure. reserved:unused pointer.
Optional function defined by dynamically linked libraries.
The VM calls JNI_OnLoad when the native library is loaded (for example, through System.loadLibrary).
return: Return the required JNI_VERSION
constant.Such as: JNI_VERSION_1_4 or JNI_VERSION_1_1
当我们在JAVA项目中加载库时,首先调用OnLoad函数,因此我们首相实现自己的OnLoad函数:
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env = NULL;
jint result = -1;
if (vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK) {
return -1;
}
if (!registerNativeMethods(env, JNIREG_CLASS, gMethods, sizeof(gMethods) / sizeof(gMethods[0]))) {//注册方法
return -1;
}
//成功
return (result = JNI_VERSION_1_4);
}
//实现注册:
static int registerNativeMethods(JNIEnv* env, const char* className, JNINativeMethod* gMethods, int numMethods) {
jclass clazz;
clazz = env->FindClass(className);
if (clazz == NULL) {
return JNI_FALSE;
}
if ((env)->RegisterNatives(clazz, gMethods, numMethods) < 0) {
return JNI_FALSE;
}
return JNI_TRUE;
}
整体流程就是这样。
其中具体的细节,我们来看看:
①GetEnv 的使用:
GetEnv 在C++使用: jint GetEnv(void **penv, jint version);
GetEnv 在C使用: jint GetEnv(JavaVM *vm, void **env, jint version);
②#define JNIREG_CLASS "javaTestJNI/myJavaTestJni" //指定要注册的JAVA类(包/类)
③实现我们要注册的函数方法数组:
static JNINativeMethod gMethods[] = { //任意添加我们自己的方法
{ "sum", "(II)I", (void*)sum },
};
其中:JNINativeMethod类型定义可在jni.h查看,
typedef struct {
char *name;
char *signature;
void *fnPtr;
} JNINativeMethod;
同时需要学习的是:参数的signature的官方定义:
eg: 本例中:int sum(int , int) --> (II)I
④jclass FindClass(JNIEnv *env, const char *name);
返回值:完全限定的类名(即包名,由“/”分隔,后跟类名).
欢迎各位交流指正!