一、 JNI 静态注册
① 在 Android 的 Java 层定义方法 : 在 MainActivity 类中定义 如下 Native 方法 ;
public native String stringFromJNI();
② Native 方法实现 : 下面是一个 Native 方法实现的示例 ;
extern "C"
JNIEXPORT jstring JNICALL
Java_kim_hsl_jni_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
// 创建 C++ 字符串
std::string hello = "Hello from C++";
// 返回 jstring 类型的字符串
return env->NewStringUTF(hello.c_str());
}
-
extern “C” : 表示 C 语言 和 C++ 的兼容 ;
-
JNIEnv *env : 其中第一个参数 JNIEnv *env 代表了 JNI 环境 ;
-
jobject 参数 : 该 Native 方法定义在 MainActivity 类中 ;
非静态方法 : 如果该方法是非静态方法 , 那么 jobject 参数表示 MainActivity 类的对象 ;
静态方法 : 如果该方法是静态方法 , 那么 jobject 参数表示 MainActivity.class ( Class 对象 ) ;
二、JNI动态注册
package com.classloading;
class NativeLib{
public static native String getName(int number);
}
按照约定,需要在本地文件中有如下声明:
JNIEXPORT jstring JNICALL Java_com_classloading_NativeLib_getName(JNIEnv *env,jobject thiz,jint number);
不过现在我们声明了一个没有按照JNI规范命名的本地函数,如下:
JNIEXPORT jstring JNICALL getName(JNIEnv *env, jclass clazz);
必须使用动态关联的方式实现Java方法与本地函数的映射,代码如下:
extern "C"
JNIEXPORT jstring JNICALL getName(JNIEnv *env, jobject thiz, int number) {
printf("number is %d",number);
return env->NewStringUTF("hello world");
}
static const char *CLASS_NAME = "com/classloading/NativeLib"; // 类名
static JNINativeMethod method = { // 本地方法描述
"getName", // Java方法名
"(I)Ljava/lang/String;", // Java方法签名
(void *) getName // 绑定到对应的本地函数
};
static bool bindNative(JNIEnv *env) {
jclass clazz;
clazz = env->FindClass(CLASS_NAME);
if (clazz == NULL) {
return false;
}
return env->RegisterNatives(clazz, &method, 1) == 0;
}
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv *env = NULL;
jint result = -1;
if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
return result;
}
bool res = bindNative(env);
printf("bind result is %s",res?"ok":"error");
// 返回JNI的版本
return JNI_VERSION_1_6;
}