@[Android JNINativeMethod介绍]
Android JNI 数据结构JNINativeMethod说明
Andoird 中使用了一种不同传统Java JNI的方式来定义其native的函数。
其中很重要的区别是Andorid使用了一种Java 和 C 函数的映射表数组,并在其中描述了函数的参数和返回值。这个数组的类型是JNINativeMethod,定义如下:
typedef struct {const char* name;const char* signature;void* fnPtr;
} JNINativeMethod;
-
第一个变量name是Java中函数的名字。
-
第二个变量signature,用字符串是描述了函数的参数和返回值,例如
"()V"
"(II)V"
"(Ljava/lang/String;Ljava/lang/String;)V"
实际上这些字符是与函数的参数类型一一对应的。
“()” 中的字符表示参数,后面的则代表返回值。例如"()V" 就表示void Func();
“(II)V” 表示 void Func(int, int);
普通类型
字符 Java类型 C类型V void void
Z jboolean boolean
I jint int
J jlong long
D jdouble double
F jfloat float
B jbyte byte
C jchar char
S jshort short
数组类型
以"["开始,用两个字符表示[I jintArray int[]
[F jfloatArray float[]
[B jbyteArray byte[]
[C jcharArray char[]
[S jshortArray short[]
[D jdoubleArray double[]
[J jlongArray long[]
[Z jbooleanArray boolean[]
上面的都是基本类型。
如果Java函数的参数是class,则以"L"开头,以";“结尾
中间是用”/" 隔开的包及类名。
而其对应的C函数名的参数则为jobject.
一个例外是String类,其对应的类为jstring
如:
Ljava/lang/String; String jstring
Ljava/net/Socket; Socket jobject
如果JAVA函数位于一个嵌入类,则用$作为类名间的分隔符。
例如
"(Ljava/lang/String;Landroid/os/FileUtils$FileStatus;)Z"
ijkplayer中的定义为样例参考
static JNINativeMethod g_methods[] = {{"_setDataSource", "(Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V", (void *) IjkMediaPlayer_setDataSourceAndHeaders},{ "_setDataSourceFd", "(I)V", (void *) IjkMediaPlayer_setDataSourceFd },{ "_setDataSource", "(Ltv/danmaku/ijk/media/player/misc/IMediaDataSource;)V", (void *)IjkMediaPlayer_setDataSourceCallback },{ "_setAndroidIOCallback", "(Ltv/danmaku/ijk/media/player/misc/IAndroidIO;)V", (void *)IjkMediaPlayer_setAndroidIOCallback },{ "_setVideoSurface", "(Landroid/view/Surface;)V", (void *) IjkMediaPlayer_setVideoSurface },{ "_prepareAsync", "()V", (void *) IjkMediaPlayer_prepareAsync },{ "_start", "()V", (void *) IjkMediaPlayer_start },{ "_stop", "()V", (void *) IjkMediaPlayer_stop },{ "seekTo", "(J)V", (void *) IjkMediaPlayer_seekTo },{ "_pause", "()V", (void *) IjkMediaPlayer_pause },{ "isPlaying", "()Z", (void *) IjkMediaPlayer_isPlaying },{ "getCurrentPosition", "()J", (void *) IjkMediaPlayer_getCurrentPosition },{ "getDuration", "()J", (void *) IjkMediaPlayer_getDuration },{ "_release", "()V", (void *) IjkMediaPlayer_release },{ "_reset", "()V", (void *) IjkMediaPlayer_reset },{ "setVolume", "(FF)V", (void *) IjkMediaPlayer_setVolume },{ "getAudioSessionId", "()I", (void *) IjkMediaPlayer_getAudioSessionId },{ "native_init", "()V", (void *) IjkMediaPlayer_native_init },{ "native_setup", "(Ljava/lang/Object;)V", (void *) IjkMediaPlayer_native_setup },{ "native_finalize", "()V", (void *) IjkMediaPlayer_native_finalize },{ "_setOption", "(ILjava/lang/String;Ljava/lang/String;)V", (void *) IjkMediaPlayer_setOption },{ "_setOption", "(ILjava/lang/String;J)V", (void *) IjkMediaPlayer_setOptionLong },{ "_getColorFormatName", "(I)Ljava/lang/String;", (void *) IjkMediaPlayer_getColorFormatName },{ "_getVideoCodecInfo", "()Ljava/lang/String;", (void *) IjkMediaPlayer_getVideoCodecInfo },{ "_getAudioCodecInfo", "()Ljava/lang/String;", (void *) IjkMediaPlayer_getAudioCodecInfo },{ "_getMediaMeta", "()Landroid/os/Bundle;", (void *) IjkMediaPlayer_getMediaMeta },{ "_setLoopCount", "(I)V", (void *) IjkMediaPlayer_setLoopCount },{ "_getLoopCount", "()I", (void *) IjkMediaPlayer_getLoopCount },{ "_getPropertyFloat", "(IF)F", (void *) ijkMediaPlayer_getPropertyFloat },{ "_setPropertyFloat", "(IF)V", (void *) ijkMediaPlayer_setPropertyFloat },{ "_getPropertyLong", "(IJ)J", (void *) ijkMediaPlayer_getPropertyLong },{ "_setPropertyLong", "(IJ)V", (void *) ijkMediaPlayer_setPropertyLong },{ "_setStreamSelected", "(IZ)V", (void *) ijkMediaPlayer_setStreamSelected },{ "native_profileBegin", "(Ljava/lang/String;)V", (void *) IjkMediaPlayer_native_profileBegin },{ "native_profileEnd", "()V", (void *) IjkMediaPlayer_native_profileEnd },{ "native_setLogLevel", "(I)V", (void *) IjkMediaPlayer_native_setLogLevel },{ "_setFrameAtTime", "(Ljava/lang/String;JJII)V", (void *) IjkMediaPlayer_setFrameAtTime },
};
- 第三个变量fnPtr是函数指针,指向C函数。