android JNI调用c组件的说明.doc.doc

上传人:ng****60 文档编号:2244252 上传时间:2019-05-02 格式:DOC 页数:27 大小:32.69KB
下载 相关 举报
android JNI调用c组件的说明.doc.doc_第1页
第1页 / 共27页
android JNI调用c组件的说明.doc.doc_第2页
第2页 / 共27页
android JNI调用c组件的说明.doc.doc_第3页
第3页 / 共27页
android JNI调用c组件的说明.doc.doc_第4页
第4页 / 共27页
android JNI调用c组件的说明.doc.doc_第5页
第5页 / 共27页
点击查看更多>>
资源描述

1、android JNI文章分类:移动开发 Java Native Interface (JNI)标准是 java 平台的一部分,它允许 Java 代码和其他语言写的代码进行交互。JNI 是本地编程接口,它使得在 Java 虚拟机 (VM) 内部运行的 Java 代码能够与用其它编程语言(如 C、C+ 和汇编语言)编写的应用程序和库进行交互操作。1.从如何载入.so 档案谈起由于 Android 的应用层的类都是以 Java 写的,这些 Java 类编译为 Dex 型式的 Bytecode 之后,必须靠 Dalvik 虚拟机(VM: Virtual Machine)来执行。VM在 Android

2、 平台里,扮演很重要的角色。此外,在执行 Java 类的过程中,如果 Java 类需要与 C 组件沟通时,VM 就会去载入 C 组件,然后让 Java 的函数顺利地调用到 C 组件的函数。此时,VM扮演着桥梁的角色,让 Java 与 C 组件能通过标准的 JNI 介面而相互沟通。应用层的 Java 类是在虚拟机(VM: Vitual Machine)上执行的,而 C 件不是在 VM 上执行,那么 Java 程式又如何要求 VM 去载入(Load)所指定的 C 组件呢? 可使用下述指令:System.loadLibrary(*.so 的档案名);例如,Android 框架里所提供的 MediaP

3、layer.java 类,含指令:public class MediaPlayer static System.loadLibrary(“media_jni“);这要求 VM 去载入 Android 的/system/lib/libmedia_jni.so 档案。载入*.so 之后,Java 类与*.so 档案就汇合起来,一起执行了。2.如何撰写*.so 的入口函数- JNI_OnLoad()与 JNI_OnUnload()函数的用途当 Android 的 VM(Virtual Machine)执行到 System.loadLibrary()函数时,首先会去执行 C 组件里的 JNI_OnLo

4、ad()函数。它的用途有二:(1)告诉 VM 此 C 组件使用那一个 JNI 版本。如果你的*.so 档没有提供JNI_OnLoad()函数,VM 会默认该*.so 档是使用最老的 JNI 1.1 版本。由于新版的 JNI 做了许多扩充,如果需要使用 JNI 的新版功能,例如 JNI 1.4 的java.nio.ByteBuffer,就必须藉由 JNI_OnLoad()函数来告知 VM。(2)由于 VM 执行到 System.loadLibrary()函数时,就会立即先呼叫JNI_OnLoad(),所以 C 组件的开发者可以藉由 JNI_OnLoad()来进行 C 组件内的初期值之设定(Ini

5、tialization) 。例如,在 Android 的/system/lib/libmedia_jni.so 档案里,就提供了JNI_OnLoad()函数,其程式码片段为:/#define LOG_NDEBUG 0#define LOG_TAG “MediaPlayer-JNI“jint JNI_OnLoad(JavaVM* vm, void* reserved)JNIEnv* env = NULL;jint result = -1;if (vm-GetEnv(void*) goto bail;assert(env != NULL);if (register_android_media_Me

6、diaPlayer(env) GetEnv(void*) goto bail;由于 VM 通常是多执行绪(Multi-threading)的执行环境。每一个执行绪在呼叫JNI_OnLoad()时,所传递进来的 JNIEnv 指标值都是不同的。为了配合这种多执行绪的环境,C 组件开发者在撰写本地函数时,可藉由 JNIEnv 指标值之不同而避免执行绪的资料冲突问题,才能确保所写的本地函数能安全地在 Android的多执行绪 VM 里安全地执行。基于这个理由,当在呼叫 C 组件的函数时,都会将 JNIEnv 指标值传递给它,如下:jint JNI_OnLoad(JavaVM* vm, void* r

7、eserved)JNIEnv* env = NULL;if (register_android_media_MediaPlayer(env) MonitorEnter(env, obj) != JNI_OK) 查看是否已经有其他执行绪进入此物件,如果没有,此执行绪就进入该物件里执行了。还有,也可撰写下述指令:if (*env)-MonitorExit(env, obj) != JNI_OK) 查看是否此执行绪正在此物件内执行,如果是,此执行绪就会立即离开。3.registerNativeMethods()函数的用途应用层级的 Java 类别透过 VM 而呼叫到本地函数。一般是仰赖 VM 去寻找

8、*.so里的本地函数。如果需要连续呼叫很多次,每次都需要寻找一遍,会多花许多时间。此时,组件开发者可以自行将本地函数向 VM 进行登记。例如,在Android 的/system/lib/libmedia_jni.so 档案里的代码段如下:/#define LOG_NDEBUG 0#define LOG_TAG “MediaPlayer-JNI“static JNINativeMethod gMethods = “setDataSource“, “(Ljava/lang/String;)V“,(void *)android_media_MediaPlayer_setDataSource,“set

9、DataSource“, “(Ljava/io/FileDescriptor;JJ)V“,(void *)android_media_MediaPlayer_setDataSourceFD,“prepare“, “()V“, (void *)android_media_MediaPlayer_prepare,“prepareAsync“, “()V“, (void *)android_media_MediaPlayer_prepareAsync,“_start“, “()V“, (void *)android_media_MediaPlayer_start,“_stop“, “()V“, (v

10、oid *)android_media_MediaPlayer_stop,“getVideoWidth“, “()I“, (void *)android_media_MediaPlayer_getVideoWidth,“getVideoHeight“, “()I“, (void *)android_media_MediaPlayer_getVideoHeight,“seekTo“, “(I)V“, (void *)android_media_MediaPlayer_seekTo,“_pause“, “()V“, (void *)android_media_MediaPlayer_pause,“

11、isPlaying“, “()Z“, (void *)android_media_MediaPlayer_isPlaying,“getCurrentPosition“, “()I“, (void *)android_media_MediaPlayer_getCurrentPosition,“getDuration“, “()I“, (void *)android_media_MediaPlayer_getDuration,“_release“, “()V“, (void *)android_media_MediaPlayer_release,“_reset“, “()V“, (void *)a

12、ndroid_media_MediaPlayer_reset,“setAudioStreamType“,“(I)V“, (void *)android_media_MediaPlayer_setAudioStreamType,“setLooping“, “(Z)V“, (void *)android_media_MediaPlayer_setLooping,“setVolume“, “(FF)V“, (void *)android_media_MediaPlayer_setVolume,“getFrameAt“, “(I)Landroid/graphics/Bitmap;“,(void *)a

13、ndroid_media_MediaPlayer_getFrameAt,“native_setup“, “(Ljava/lang/Object;)V“,(void *)android_media_MediaPlayer_native_setup,“native_finalize“, “()V“, (void *)android_media_MediaPlayer_native_finalize,;static int register_android_media_MediaPlayer(JNIEnv *env)return AndroidRuntime:registerNativeMethod

14、s(env,“android/media/MediaPlayer“, gMethods, NELEM(gMethods);jint JNI_OnLoad(JavaVM* vm, void* reserved)if (register_android_media_MediaPlayer(env) 对照表,在程序执行时,可多次呼叫 registerNativeMethods()函数来更换本地函数之指针,而达到弹性抽换本地函数之目的。4.Andoird 中使用了一种不同传统 Java JNI 的方式来定义其 native 的函数。其中很重要的区别是 Andorid 使用了一种 Java 和 C 函数

15、的映射表数组,并在其中描述了函数的参数和返回值。这个数组的类型是 JNINativeMethod,定义如下:typedef struct const char* name; /*Java 中函数的名字*/ const char* signature; /*描述了函数的参数和返回值*/void* fnPtr; /*函数指针,指向 C 函数*/ JNINativeMethod;其中比较难以理解的是第二个参数,例如“()V“(II)V“(Ljava/lang/String;Ljava/lang/String;)V“实际上这些字符是与函数的参数类型一一对应的。“()“ 中的字符表示参数,后面的则代表返

16、回值。例如“()V“ 就表示 void Func();“(II)V“ 表示 void Func(int, int);具体的每一个字符的对应关系如下字符 Java 类型 C 类型V void voidZ jboolean booleanI jint intJ jlong longD jdouble doubleF jfloat floatB jbyte byteC jchar charS jshort short数组则以“开始,用两个字符表示I jintArray intF jfloatArray floatB jbyteArray byteC jcharArray charS jshortAr

17、ray shortD jdoubleArray doubleJ jlongArray longZ jbooleanArray boolean上面的都是基本类型。如果 Java 函数的参数是 class,则以“L“开头,以“;“结尾,中间是用“/“ 隔开的包及类名。而其对应的 C 函数名的参数则为 jobject. 一个例外是 String 类,其对应的类为 jstringLjava/lang/String; String jstringLjava/net/Socket; Socket jobject如果 JAVA 函数位于一个嵌入类,则用$作为类名间的分隔符。例如 “(Ljava/lang/S

18、tring;Landroid/os/FileUtils$FileStatus;)Z“Android JNI 编程实践一、直接使用 java 本身 jni 接口(windows/ubuntu)1.在 Eclipsh 中新建一个 android 应用程序。两个类:一个继承于Activity,UI 显示用。另一个包含 native 方法。编译生成所有类。jnitest.java 文件:package com.hello.jnitest;import android.app.Activity;import android.os.Bundle;public class jnitest extends Activity /* Called when the activity is first created. */Overridepublic void onCreate(Bundle savedInstanceState)

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育教学资料库 > 精品笔记

Copyright © 2018-2021 Wenke99.com All rights reserved

工信部备案号浙ICP备20026746号-2  

公安局备案号:浙公网安备33038302330469号

本站为C2C交文档易平台,即用户上传的文档直接卖给下载用户,本站只是网络服务中间平台,所有原创文档下载所得归上传人所有,若您发现上传作品侵犯了您的权利,请立刻联系网站客服并提供证据,平台将在3个工作日内予以改正。