不同编程语言之间的函数的关联
来源:互联网 发布:网络被劫持了怎么办 编辑:程序博客网 时间:2024/06/07 07:50
一、JNI(Java Native Interface, Java本地调用)
作用:在Java程序中的函数可以调用C/C++编写的函数;
在C/C++程序中的函数可以调用Java编写的函数;
JNI实例
Java(MediaScanner)<——>JNI(libmedia_jni.so)<——>Native(libmedia.so)
在Java层中的MediaScanner类中有一些函数需要由Native层来实现;
MediaScanner将通过JNI库libmedia_jni.so和Native层的libmedia.so交互;
从上面的分析可知,JNI层必须实现为动态库的形式,这样Java虚拟机才能加载和调用 它的函数;
Java层的MediaScanner分析
MediaScanner.java
public class MediaScanner{ static { /*1)加载对应的JNI库,media_jni是JNI库的名字,在实际加载动态库的时候将其拓展成libmedia_jni.so,windows平台上拓展为media_jni.dll*/ System.loadLibrary("media_jni"); native_init(); //调用native_init函数 } ...... //2)声明一个native函数,native为Java关键字,表示它将由JNI层完成。 private static native final void native_init(); ...... private native void processFile(String path, String mimeType, MediaScannerClient client); ......}
上面的代码列出了两个要点:一个是加载JNI库,另一个是Java的native函数。
加载JNI库
原则上在调用native函数前,都可以加载;通常在类的static语句中加载;
调用System.loadLibrary()方法;
从上面的代码可以发现,native_init和processFile函数前都有Java的关键字native,它表示这两个函数将由JNI层来实现;
JNI层MediaScanner的分析
MediaScanner的JNI层代码在android_media_MediaScanner.cpp中
android_media_MediaScanner.cpp
//native_init的JNI实现static void android_media_MediaScanner_native_init(JNIEnv *env){ ......}//processFile的JNI层实现static void android_media_MediaScanner_processFile(JNIEnv *env, jobject thiz, jstring path, jstring mimeType, jobject client){ ......}
Java层native_init函数如何对应JNI层的android_media_MediaScanner_native_init函数?
注册JNI函数
native_init函数位于android.media这个包中,它的全路径名应该是android.media.MediaScanner.native_init,而JNI层函数的名字是android_media_MediaScanner_native_init;
JNI层中把Java函数名称中的“.”换成“_”,通过这种方式native_init找到JNI层的对应函数android_media_MediaScanner_native_init;
1、静态方法
使用Java的工具程序javah找对应的JNI函数,流程如下:
先编写Java代码,然后编译生成.class文件。
使用Java工具程序javah,$ javah -o output packagename.classname
之后生成output.h的JNI层头文件,其中packagename.classname是Java代码编译后的class文件,在output.h中声明了对应的JNI层函数,只要实现里面的函数即可。
如MediaScanner对应JNI层头文件就是android_media_MediaScanner.h
对应关系:
当Java层调用native_init函数时,它会从对应的JNI库中寻找Java_android_media_MediaScanner_native_init函数,如果没有就报错。如果找到就为这两个函数建立一个关联关系,就是保存JNI层函数的函数指针,以后再调用就可以使用这个函数指针了,这些工作是由虚拟机完成的。
2、动态注册
JNI中使用JNINativeMethod结构保存上面Java和JNI层函数的一一对应的关系;
//定义一个JNINativeMethod数组,其成员就是Java层中所有的native函数的一一对应关系
static JNINativeMethod gMethods[] = { ...... { "processFile" //Java中native函数的函数名 //processFile的签名信息,签名信息由函数参数及返回值构成; "(Ljava/lang/String;Ljava/lang/String;Landroid/media/MediaScannerClient;)V", (void *)android_media_MediaScanner_processFile //JNI层对应的函数指针 }, ...... { "native_init", "()V", (void *)android_media_MediaScanner_native_init },};//注册JNINativeMethod数组int register_android_media_MediaScanner(JNIEnv *env){ //调用AndroidRuntime的registerNativeMethods函数,第二个参数表明是Java中的哪个类 return AndroidRuntime::registerNativeMethods(env, "andorid/media/MediaScanner", gMethods, NELEM(gMethods));}
AndroidRunTime提供了一个registerNativeMethods函数来完成注册工作,下面看registerNativeMethods的实现,代码如下:
int AndroidRuntime::registerNativeMethods(JNIEnv* env, const char* className, const JNINativeMethod* gMethod, int numMethods){ //调用jniRegisterNativeMethods函数完成注册 return jniRegisterNativeMethods(env, className, gMethods, numMethods);}其中jniRegisterNativeMethods是Android平台为了方便JNI使用而提供的一个帮助函数,代码如下:
int jniRegisterNativeMethods(JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods){ jclass clazz; clazz = (*env)->FindClass(env, className); ...... //实际上是调用JNIEnv的RegisterNatives函数完成注册的 if((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0) { return -1; } return 0;}
动态注册的工作只用两个函数就能完成。
jclass clazz = (*env)->FindClass(env, className);(*env)->RegisterNatives(env, clazz, gMethods, numMethods);
动态注册的函数,当Java层通过System.loadLibrary加载完JNI动态库后,紧接着会查找该库中一个叫JNI_OnLoad的函数,调用它完成注册;
建议实现这个JNI_OnLoad函数,在其中做一些初始化的工作;
函数签名信息的生成
java提供了一个javap的工具可以帮助生成函数和变量的签名信息;
$ java -s -p xxx
其中xxx为编译生成的class文件,s表示输出内部数据类型的签名信息,p表示打印所有函数和成员的签名信息,默认只会答应public的成员和函数的签名信息;
二、XPCOM组件
- 不同编程语言之间的函数的关联
- 不同编程语言之间转换的项目矩阵
- 不同编程语言之间转换的项目矩阵
- 不同系统不同语言之间的交互
- 不同阶段人选不同的编程语言
- 两台不同的数据库之间数据关联
- 不同语言之间的DLL调用
- 不同系统不同语言之间的交互使
- Java不同系统不同语言之间的交互
- 不同数据库之间的基本函数
- 关于c语言不同文件之间直接函数接口引用的简介
- 同一个C语言工程不同C文件之间的函数互相调用问题(一)
- 同一个C语言工程不同C文件之间的函数互相调用问题(二)
- 同一个C语言工程不同C文件之间的函数互相调用问题(三)
- 学习不同编程语言的重要性
- 学习不同编程语言的重要性
- 学习不同编程语言的重要性
- [博文]学习不同编程语言的重要性
- Windows下我的sublime text3
- PHP打开乱码问题
- android6.0如何删除桌面上的导航栏、状态栏、google搜索栏和系统搜索栏
- SQLite开源库LitePal
- String、StringBuffer 和 StringBuilder 的区别
- 不同编程语言之间的函数的关联
- ViewPager java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0
- jQuery学习 二 jQuery 效果
- python topn
- 树-堆结构
- iOS 一些相似属性的理解
- 自定义控件之九宫格
- html5shiv为IE兼容html5利器
- Hive 模式设计和语言规范