代码比较简单就不放链接了。
静态注册和动态注册的不同点都在C++层,使用示例用的java代码是一样的。
废话不多说,直接发车。
静态注册
实现步骤:
1、在java层中写native函数,Alt+Enter 即可生成对应的C++函数,IDEA会直接帮你注册好方法。
2、在C++函数里面实现逻辑
//--------------------------------java层---------------------------------
static {
System.loadLibrary("native-lib");
}
public native void printLog(String str);
//--------------------------------c++层--------------------------------
extern "C"
JNIEXPORT void JNICALL
Java_com_example_jni_1thread_MainActivity_printLog(JNIEnv *env, jobject thiz, jstring str) {
const char * myLog = env->GetStringUTFChars(str, nullptr);
LOGE("JNISTUD:在C++层中打印日志:%s", myLog);
}
//--------------------------------运行日志--------------------------------
JNISTUDY:在C++层中打印日志:hello C++
动态注册
实现步骤:
1、在java层中写native函数。(PS:下面java层的演示代码和静态注册的方法一致)
2、重写C/C++的JNI_Onload()函数
3.通过JavaVM获得JNIEnv(JNIEnv可以看成java和C++之间的控制器,一些交互操作都需要该类来实现)
4.编写JNINativeMethod数组,里面需要java层函数名、函数签名、C++层对应函数的具体实现。
5.使用JNIEnvd的RegisterNatives函数进行动态注册
//--------------------------------java层---------------------------------
//步骤一
static {
System.loadLibrary("native-lib");//此处会调用native-lib的JNI_OnLoad函数,类似java中的构造函数
}
public native void printLog(String str);
//--------------------------------C++层---------------------------------
//对应函数的具体实现
void printCLog(JNIEnv *env, jobject thiz, jstring str) {
const char * myLog = env->GetStringUTFChars(str, nullptr);
LOGE("JNISTUD:在C++层中打印日志:%s", myLog);
}
//步骤四
static const JNINativeMethod jniNativeMethod [] = {
{"printLog", //函数名
"(Ljava/lang/String;)V", //函数签名
(void *)(printCLog)} //函数指针
};
//步骤二
JNIEXPORT jint JNI_OnLoad(JavaVM * javaVm, void *) {
//步骤三
JNIEnv *jniEnv = nullptr;
int result = javaVm->GetEnv(reinterpret_cast<void **>(&jniEnv), JNI_VERSION_1_6); //给JNIEnv赋值
if (result != JNI_OK) { //JNI_OK为0
return -1;
}
//步骤五
const char * mainActivityClassName = "com/example/jni_thread/MainActivity";
jclass mainActivityClass = jniEnv->FindClass(mainActivityClassName);
jniEnv->RegisterNatives(mainActivityClass, //需要注册的函数所在的java类
jniNativeMethod, //需要注册的函数的数组
sizeof(jniNativeMethod) / sizeof(JNINativeMethod)); //数组长度
return JNI_VERSION_1_6;
}
//--------------------------------运行日志--------------------------------
JNISTUDY:在C++层中打印日志:hello C++
java方法签名查找表:签名表查阅链接
总结
静态注册
- 优点:不难看出使用静态注册时比较方便(代码自动生成),便于使用与理解。
- 缺点:在java层调用native函数时,需要去匹配C++层的函数名,因此性能上可能会出现一定的影响,而且在修改函数名的时候比较麻烦,灵活性较低。
动态注册
- 优点:在System.loadLib的时候就完成了加载,所以源码层都是动态注册(为了性能),修改函数名、类名、包名啥的,只需要少量修改代码,灵活性还是相对比较高的。
- 缺点:麻烦,不利于理解,,开发的时候一般不会用动态注册,因为确实麻烦.......(偷懒 嘿嘿嘿嘿)