在上一篇文章中介绍了JNI,以及java调用JNI,这篇讲一下 JNI调用java方法。
通过使用合适的JNI函数,你可以创建Java对象,get、set 静态(static)和 实例(instance)的域,调用静态(static)和实例(instance)函数。JNI通过ID识别域和方法,一个域或方法的ID是任何处理域和方法的函数的必须参数。
下表列出了用以得到静态(static)和实例(instance)的域与方法的JNI函数。每个函数接受(作为参数)域或方法的类,它们的名称,符号和它们对应返回的jfieldID或jmethodID。
函数 | 描述 |
GetFieldID | 得到一个实例的域的ID |
GetStaticFieldID | 得到一个静态的域的ID |
GetMethodID | 得到一个实例的方法的ID |
GetStaticMethodID | 得到一个静态方法的ID |
构造一个Java对象的实例
首先是获得一个Java类的class引用 (*env)->FindClass(env, "Lpackagename/classname;"); 请注意参数:Lpackagename/classname; ,L代表这是在描述一个对象类型,packagename/classname是该对象耳朵class路径,请注意一定要以分号(;)结束!
然后是获取函数的id,jmethodID id = env->GetMethodID(cls, "", "(D)V"); 第一个是刚刚获得的class引用,第二个是方法的名称,最后一个就是方法的签名了
JNINativeMethod的定义如下:
第一个变量name是Java中函数的名字。
第二个变量signature,用字符串是描述了函数的参数和返回值
第三个变量fnPtr是函数指针,指向C函数。
其中比较难以理解的是第二个参数,例如
"()V"
"(II)V"
"(Ljava/lang/String;Ljava/lang/String;)V"
实际上这些字符是与函数的参数类型一一对应的。
"()" 中的字符表示参数,后面的则代表返回值。例如"()V" 就表示void Func();
"(II)V" 表示 void Func(int, int);
那其他情况呢?请查看下表:
类型 | 符号 |
boolean | Z |
byte | B |
char | C |
short | S |
int | I |
long | L |
float | F |
double | D |
void | V |
object对象 | LClassName; L类名; |
Arrays | [array-type [数组类型 |
methods方法 | (argument-types)return-type (参数类型)返回类型 |
稍稍补充一下:
1、方法参数或者返回值为java中的对象时,签名中必须以“L”加上其路径,不过此路径必须以“/”分开,自定义的对象也使用本规则
比如说 java.lang.String为“java/lang/String”,com.nedu.jni.helloword.Student为"Lcom /nedu/jni/helloword/Student;"
2、方法参数或者返回值为数组类型时,请前加上[
例如[I表示 int[],[[[D表示 double[][][],即几维数组就加几个[
其参数的意义:
env-->JNIEnv
cls-->第一步获取的jclass
"callback"-->要调用的方法名
"(I)V"-->方法的Signature, 签名同前面的JNI规则。
使用CallVoidMethod方法调用方法。参数的意义:
env-->JNIEnv
obj-->通过本地方法穿过来的jobject
mid-->要调用的MethodID(即第二步获得的MethodID)
depth-->方法需要的参数(对应方法的需求,添加相应的参数)
注:这里使用的是CallVoidMethod方法调用,因为没有返回值,如果有返回值的话使用对应的方法,在后面会提到。
CallVoidMethod CallStaticVoidMethod
从java程序中传过去的String对象在本地方法中对应的是jstring类型,jstring类型和c中的char*不同,所以如果你直接当做char*使用的话,就会出错。因此在使用之前需要将jstring转换成为c/c++中的char*,这里使用JNIEnv提供的方法转换。
const char *str = (*env)->GetStringUTFChars(env, jstr, 0); (*env)->ReleaseStringUTFChars(env, jstr, str);
这里使用GetStringUTFChars方法将传进来的prompt(jstring类型)转换成为UTF-8的格式,就能够在本地方法中使用了。
注意:在使用完你所转换之后的对象之后,需要显示调用ReleaseStringUTFChars方法,让JVM释放转换成UTF-8的string的对象的空间,如果不显示的调用的话,JVM中会一直保存该对象,不会被垃圾回收器回收,因此就会导致内存溢出。
下面是Jni访问String对象的一些方法:
下面提供两个String对象和char*互转的方法:
/* c/c++ string turn to java jstring */其实在JNI中调用java的特性和在java中差别不大都是相同思想,比如先找类,再找构造,再创建对象,然后就进行一系列操作...等等。
参考:http://zhiweiofli.iteye.com/blog/1830321
如有问题请留言,转载注明出处。
java native interface JNI 调用Java方法,布布扣,bubuko.com
java native interface JNI 调用Java方法
原文:http://blog.csdn.net/rain_butterfly/article/details/25127923