JNI的学习
来源:互联网 发布:工程套价软件 编辑:程序博客网 时间:2024/06/05 18:30
一.JNI设计的目的
1.c/c++不同点在JNI
- Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
- jobject thiz )
- {
- return (*env)->NewStringUTF(env, "Hello World from JNI!");
- }
JavaC/C++字节数booleanjboolean1bytejbyte1charjchar2shortjshort2intjint4longjlong8floatjfloat4doublejdouble8
对于数组型参数,
JavaC/C++boolean[ ]JbooleanArraybyte[ ]JbyteArraychar[ ]JcharArrayshort[ ]JshortArrayint[ ]JintArraylong[ ]JlongArrayfloat[ ]JfloatArraydouble[ ]JdoubleArray对于上述类型数组,有一组函数与其对应。以下函数中 Xxx 为对应类型。
xxx * GetXxxArrayElements(xxxArray array, jboolean *isCopy)
产生一个指向 Java 数组元素的 C 指针。不再需要时,需将此指针传给 ReleaseXxxArrayElemes。
3.JNI相关操作
- 类的相关操作(获取类)
jclass FindClass(JNIEnv *env, const char *name); 查找类
需要注意的是第二个参数为const char*类型的,我们如果从Java从层传入unicode编码的jstring类型需要使用GetStringUTFChars函数转换成utf8的const char*,记得后面ReleaseStringUTFChars 函数,如果成功返回这个Java类的对象jclass.
jclass GetSuperclass(JNIEnv *env, jclass clazz); 获取父类或者说超类
该函数的第二个参数为jclass类,我们调用时传入的是子类,否则返回将是NULL
jboolean IsAssignableFrom(JNIEnv *env, jclass clazz1,jclass clazz2); 判断class1对象能否安全的强制转换为class2对象
jclass GetObjectClass(JNIEnv *env, jobject obj); 通过对象获取这个类
jboolean IsInstanceOf(JNIEnv *env, jobject obj,jclass clazz); 判断对象是否为某个类的实例
- 调用Java方法 (call java的方法)
jmethodID GetMethodID(JNIEnv *env, jclass clazz,const char *name, const char *sig); 获取一个Java方法的ID
这个函数将返回非静态类或接口实例方法的方法 ID
NativeType CallXXXMethod (JNIEnv *env, jobject obj,jmethodID methodID, va_list args); 调用XXX类型的Java 方法
执行Java类中某个方法,需要注意的是这个里的java类是非静态的,由于Java的方法的类型比较多,所以该函数可能有以下几种形式, 如 CallObjectMethod,CallBooleanMethod,CallByteMethod,CallCharMethod,CallShortMethod,CallIntMethod,CallLongMethod,CallFloatMethod,CallDoubleMethod和CallVoidMethod,
va_list args是代表参数列表。
- 访问Java对象的域
Java对象的域或者说字段、属性(Field) 类似方法的执行
1. jfieldID GetFieldID(JNIEnv *env, jclass clazz,const char *name, const char *sig); 获取实例对象的域ID
2. NativeType GetXXXField(JNIEnv *env, jobject obj,jfieldID fieldID);
类似GetXXXMethod函数,可能有的类型有 GetObjectField,GetBooleanField,GetByteField,GetCharField,GetShortField,GetIntField,GetLongField,GetFloatField,GetDoubleField。
3. void SetXXXField(JNIEnv *env, jobject obj, jfieldID fieldID,NativeType value);
Java的域可以赋值的,可能有的类型有 SetObjectField,SetBooleanField,SetByteField,SetCharField,SetShortField,SetIntField,SetLongField,SetFloatField,SetDoubleField
4.jfieldID GetStaticFieldID(JNIEnv *env, jclass clazz,const char *name, const char *sig);
5. NativeType GetStaticXXXField(JNIEnv *env, jclass clazz,jfieldID fieldID);
6. void SetStaticXXXField(JNIEnv *env, jclass clazz,jfieldID fieldID, NativeType value);
4.Java层传入的String不能在JNI中直接转化为jstring,因为Java的内部编码为unicode,中英文的字符都是每个占两个字节,而jni中我们需要使用utf-8来表示,utf-8比较特殊中英文是不等长的,比如英文等符号的ascii占用一个字节,而中文则为三个字节,同时仍然以/n结尾
而正确的转换unicode到utf-8方法为使用GetStringUTFChars这个函数:
后面ReleaseStringUTFChars.
一.本文是主要写GetFieldID,GetMethodID方法的使用
jclass clazz=(*env)->GetObjectClass(env,thiz);//其中的clazz就是Natvie class.
void Java_com_android_jni_Native_getValue(JNIEnv * env,jobject thiz){jfieldID fid;jfieldID fNumberId;jstring jstr;jmethodID mid;const char * szTemp;jclass clazz=(*env)->GetObjectClass(env,thiz);print(clazz);fid=(*env)->GetFieldID(env,clazz,"value","Ljava/lang/String;");if(fid==NULL){return;}jstr=(*env)->GetObjectField(env,thiz,fid);szTemp=(*env)->GetStringUTFChars(env,jstr,NULL);print(szTemp);(*env)->ReleaseStringUTFChars(env,jstr,szTemp);jstr=(*env)->NewStringUTF(env,"hello world");if(jstr==NULL)return;(*env)->SetObjectField(env,thiz,fid,jstr);//call the method showMessagefNumberId=(*env)->GetStaticFieldID(env,clazz,"number","I");if(fNumberId==NULL)return;jint num=(*env)->GetStaticIntField(env,clazz,fNumberId);//print(num);(*env)->SetStaticIntField(env,clazz,fNumberId,2);mid=(*env)->GetMethodID(env,clazz,"showMessage","()V");if(mid==NULL)return ;(*env)->CallVoidMethod(env,thiz,mid);}
开始我在写这个程序的时候一直报GetFileId ..No such "value".
找了好久才发现 我在Native.java中定义的 和getValue()也是用static
然后定义的value不是static.
在fid=(*env)->GetFieldID(env,clazz,"value","Ljava/lang/String;"); 报错,是因为static方法中必须要用static的变量
所以我把getValue()方法的static方法去掉,下面是ok的代码。
void Java_com_android_jni_Native_getValue(JNIEnv * env,jobject thiz){jfieldID fid;jfieldID fNumberId;jstring jstr;jmethodID mid;const char * szTemp;jclass clazz=(*env)->GetObjectClass(env,thiz);print(clazz);fid=(*env)->GetFieldID(env,clazz,"value","Ljava/lang/String;");if(fid==NULL){return;}jstr=(*env)->GetObjectField(env,thiz,fid);szTemp=(*env)->GetStringUTFChars(env,jstr,NULL);print(szTemp);(*env)->ReleaseStringUTFChars(env,jstr,szTemp);jstr=(*env)->NewStringUTF(env,"hello world");if(jstr==NULL)return;(*env)->SetObjectField(env,thiz,fid,jstr);//call the method showMessagefNumberId=(*env)->GetStaticFieldID(env,clazz,"number","I");if(fNumberId==NULL)return;jint num=(*env)->GetStaticIntField(env,clazz,fNumberId);//print(num);(*env)->SetStaticIntField(env,clazz,fNumberId,2);mid=(*env)->GetMethodID(env,clazz,"showMessage","()V");if(mid==NULL)return ;(*env)->CallVoidMethod(env,thiz,mid);}
我本来想全部用static来解决就是
fid=(*env)->GetStaticFieldID(env,clazz,"value","Ljava/lang/String;");
不知道什么原因,还是出现上面的错误。。后续来改。
今天试getMethodId();
mid=(*env)->GetMethodID(env,clazz,"showMessage","()V");//showMessage为Java中的方法,"()V"为该方法是return void的方法。
(*env)->CallVoidMethod(env,thiz,mid);
与GetMethodID相对应的是Call**Method().
对应static的属性一定要用static的属性。
fNumberId=(*env)->GetStaticFieldID(env,clazz,"number","I");
if(fNumberId==NULL)
return;
jint num=(*env)->GetStaticIntField(env,clazz,fNumberId);
//print(num);
(*env)->SetStaticIntField(env,clazz,fNumberId,2);
参考网站学习
http://www.ibm.com/developerworks/cn/java/l-linux-jni/
http://dev.10086.cn/cmdn/bbs/redirect.php?tid=33663&goto=lastpost
http://www.android123.com.cn/androidkaifa/686.html
- JNI的学习
- jni的学习使用
- jni的c学习
- eclipse的JNI学习
- jni学习遇到的问题
- 我的JNI学习摘要(一) ---- JNI初体验
- android JNI学习之五 JNI中常用的方法
- android JNI学习之六 JNI的一个框架
- android中jni学习——jni的调用
- JNI学习,不通过h头文件调用Jni的demo
- Android JNI和NDK学习(06)--JNI的数据类型
- Android JNI和NDK学习(07)--JNI的常用API
- 学习JNI
- jni学习
- 学习JNI
- jni学习
- JNI学习
- JNI学习
- Ajax与中文乱码
- 快毕业了,怎么办,工作啊,工作,烦!
- 【Delphi】FireMonkey下的WndProc实现
- 实现TCP并发服务器之一(多进程)
- Linux网络概述
- JNI的学习
- svg webtopo原型6 事件的鼠标属性
- visio中添加表格
- DBus如何使用原始DBus库传送和接收数据
- seajs的spm使用摸索
- Android应用中通过AIDL机制实现进程间的通讯实例
- redhat,ubuntu,Fedora搭建NFS
- 【Delphi】RDP文件中的密码Hash加解密单元
- Linux中查看某个软件的安装路径