您的位置:首页 > 移动开发 > Android开发

在android中通过JNI调用本地方法

2011-07-01 12:08 363 查看
JNI的核心是JNINativeMethod结构体,在jni.h中定义:

typedef struct {
const char* name;          //JNI函数的名称
const char* signature;     //描述JNI函数的参数和返回值
void* fnPtr;               //JNI函数对应的C语言的函数指针
} JNINativeMethod;


要实现java通过JNI调用本地C函数, 要有以下几步:

一:在C/C++中对本地函数定义JNINativeMethod结构体并在系统注册

例如frameworks/base/core/jni/中的android_util_Log.cpp表示对android.util包中的Log类提供支持。这个文件首先定义了所实现的java方法列表:

static JNINativeMethod gMethods[] = {
{"isLoggable", "Ljava/lang/String;I)Z", (void*)android_util_Log_isLoggable),
{"println_native", "(IILjava/lang/String;Ljava/lang/String;)I", (void*) android_util_Log_println_native },
};


定义后只有对系统进行注册才能够使用,注册函数如下:

int register_android_util_Log(JNIEnv* env)
{
jclass clazz = env->FindClass("android/util/Log");

if (clazz == NULL) {
LOGE("Can't find android/util/Log");
return -1;
}

levels.verbose = env->GetStaticIntField(clazz, env->GetStaticFieldID(clazz, "VERBOSE", "I"));
levels.debug = env->GetStaticIntField(clazz, env->GetStaticFieldID(clazz, "DEBUG", "I"));
levels.info = env->GetStaticIntField(clazz, env->GetStaticFieldID(clazz, "INFO", "I"));
levels.warn = env->GetStaticIntField(clazz, env->GetStaticFieldID(clazz, "WARN", "I"));
levels.error = env->GetStaticIntField(clazz, env->GetStaticFieldID(clazz, "ERROR", "I"));
levels.assert = env->GetStaticIntField(clazz, env->GetStaticFieldID(clazz, "ASSERT", "I"));

return AndroidRuntime::registerNativeMethods(env, "android/util/Log", gMethods, NELEM(gMethods));
}


二:在java方法中声明为native方法。

public static native boolean isLoggable(String tag, int level);

/** @hide */ public static native int println_native(int bufID, int priority, String tag, String msg);

需要注意的是在注释中的@hide表示的是该方法虽然在java代码中是存在的,但是被隐藏的,不被视为Android的系统API。

上边的方法是在Android的系统API中增加本地接口,单一的java程序其实也是一样的方法调用本地接口,这样就无需更改系统API,android系统也提供了一个java程序直接调用本地接口的例子,在development/samples/目录下的SimpleJNI,可以参考学习下。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: