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

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

《android JNI调用c组件的说明.doc》由会员分享,可在线阅读,更多相关《android JNI调用c组件的说明.doc(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框架里所提供的MediaPlayer.java类,含指令: public class MediaPlayer static

3、 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_OnLoad()函数。它的用途有二:(1)告诉VM此C组件使用那一个JNI版本。如果你的*.so档没有提供JNI_OnLoad()函数,V

4、M会默认该*.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组件内的初期值之设定(Initialization) 。例如,在Android的/system/lib/libmedia_jni.so档案里,就提供了JNI_OnLoad()函数,其程式码片段为:/#defin

5、e LOG_NDEBUG 0#define LOG_TAG MediaPlayer-JNIjint 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 failedn); goto bail; assert(env != NULL); if (register_android_media_MediaPlayer(env) 0) LOGE(ERROR

6、: MediaPlayer native registration failedn); goto bail; if (register_android_media_MediaRecorder(env) 0) LOGE(ERROR: MediaRecorder native registration failedn); goto bail; if (register_android_media_MediaScanner(env) 0) LOGE(ERROR: MediaScanner native registration failedn); goto bail; if (register_an

7、droid_media_MediaMetadataRetriever(env) 0) LOGE(ERROR: MediaMetadataRetriever native registration failedn); goto bail; /* success - return valid version number */ result = JNI_VERSION_1_4;bail: return result;此函数回传JNI_VERSION_1_4值给VM,于是VM知道了其所使用的JNI版本了。此外,它也做了一些初期的动作(可呼叫任何本地函数),例如指令: if (register_and

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

9、叫C组件的函数时,都会将JNIEnv指标值传递给它,如下:jint JNI_OnLoad(JavaVM* vm, void* reserved)JNIEnv* env = NULL; if (register_android_media_MediaPlayer(env) MonitorEnter(env, obj) != JNI_OK) 查看是否已经有其他执行绪进入此物件,如果没有,此执行绪就进入该物件里执行了。还有,也可撰写下述指令: if (*env)-MonitorExit(env, obj) != JNI_OK) 查看是否此执行绪正在此物件内执行,如果是,此执行绪就会立即离开。3.re

10、gisterNativeMethods()函数的用途应用层级的Java类别透过VM而呼叫到本地函数。一般是仰赖VM去寻找*.so里的本地函数。如果需要连续呼叫很多次,每次都需要寻找一遍,会多花许多时间。此时,组件开发者可以自行将本地函数向VM进行登记。例如,在Android的/system/lib/libmedia_jni.so档案里的代码段如下:/#define LOG_NDEBUG 0#define LOG_TAG MediaPlayer-JNIstatic JNINativeMethod gMethods = setDataSource, (Ljava/lang/String;)V, (

11、void *)android_media_MediaPlayer_setDataSource, setDataSource, (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, (void *)android_media_MediaPlayer_stop, getVideoWidth, ()I, (void *)android_media_MediaPlayer_getVideoWidth, getVideoHeight, ()I, (void *)android_media_MediaPlayer_getVideoHeight, see

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

当前位置:首页 > 生活休闲 > 科普知识

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号