JNI函数的注册有两种方法,
一种是静态方法,需要用javah为每个声明了native函数的java类编译出的class文件生成一个头文件;
另一种是动态注册,通过数据结构保存关联关系实现注册,这里主要介绍动态注册。
1. Java 部分与静态加载相同。
2. JNI部分:
typedef struct { const char* name; //java中native函数的名字 const char* signature; //Java函数的签名信息,用字符串表示,是参数类型和返回值类型的组合 void* fnPtr; } JNINativeMethod; //JNI层函数的函数指针,void*类型
static JNINativeMethod gMethods[] = { //{"native method name from Java","(arguments type)return type", "(void*)local_native_name" {"nativeGetHelloString", "()Ljava/lang/String;", (void *)nativeGetHelloString}, {"nativeDrawFrame", "()V", (void *)nativeDrawFrame}, {"nativeSurfaceChanged", "(II)V", (void *)nativeSurfaceChanged}, {"nativeSurfaceCreated", "()V", (void *)nativeSurfaceCreated}, };
#if defined(__cplusplus) typedef _JNIEnv JNIEnv; //cpp中是一个结构 typedef _JavaVM JavaVM; #else typedef const struct JNINativeInterface* JNIEnv; //c中是一个指针。 typedef const struct JNIInvokeInterface* JavaVM; #endif
#include <string.h> #include <android/log.h> #include <jni.h> #define LOG_TAG "bbaiEGL_Dynamic" #define LOGD(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) extern "C" { /* * Class: com_example_nativeegl_MyRenderer * Method: nativeGetHelloString * Signature: ()Ljava/lang/String; */ jstring nativeGetHelloString(JNIEnv *env, jobject obj) { return env->NewStringUTF((char*)" This is calling from JNI suckers!"); } /* * Class: com_example_nativeegl_MyRenderer * Method: nativeDrawFrame * Signature: ()V */ void nativeDrawFrame(JNIEnv *env, jobject obj) { } /* * Class: com_example_nativeegl_MyRenderer * Method: nativeSurfaceChanged * Signature: (II)V */ void nativeSurfaceChanged(JNIEnv *env, jobject obj, jint width, jint height){ } /* * Class: com_example_nativeegl_MyRenderer * Method: nativeSurfaceCreated * Signature: ()V */ void nativeSurfaceCreated(JNIEnv *env, jobject obj) { } //----------------------------JNI part:Native register------------------------------------------------------ static JNINativeMethod gMethods[] = { //{"native method name from Java","(arguments type)return type", "(void*)local_native_name" {"nativeGetHelloString", "()Ljava/lang/String;", (void *)nativeGetHelloString}, {"nativeDrawFrame", "()V", (void *)nativeDrawFrame}, {"nativeSurfaceChanged", "(II)V", (void *)nativeSurfaceChanged}, {"nativeSurfaceCreated", "()V", (void *)nativeSurfaceCreated}, }; static const char* className="com/example/nativeegldynamicjni/MyRenderer"; static int registerNativeMethods(JNIEnv *env) { jclass clazz; clazz = env->FindClass(className); if (clazz == NULL) { LOGD("failed to load the class %s", className); return JNI_FALSE; } if (env->RegisterNatives(clazz, gMethods, sizeof(gMethods)/sizeof(gMethods[0])) < 0) { return JNI_FALSE; } return JNI_TRUE; } //end of registerNativeMethods jint JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv* env = NULL; jint result = -1; if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { LOGE("ERROR: GetEnv failed\n"); goto bail; } if (registerNativeMethods(env) < 0) { LOGE("ERROR: jnitest native registration failed\n"); goto bail; } result = JNI_VERSION_1_4; bail: return result; } } //end of extern "C"
#Description:makefile of Helloworld LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_CFLAGS := -Wall LOCAL_MODULE := myegl_jni LOCAL_C_INCLUDES :=$(LOCAL_PATH)/include LOCAL_CPP_EXTENSION := .cpp LOCAL_LDLIBS += -llog LOCAL_SRC_FILES := com_example_nativeegl_MyRenderer.cpp include $(BUILD_SHARED_LIBRARY)