经过使用合适的JNI函数,你能够建立Java对象,get、set 静态(static)和 实例(instance)的域,调用静态(static)和实例(instance)函数。JNI经过ID识别域和方法,一个域或方法的ID是任何处理域和方法的函数的必须参数。
下表列出了用以获得静态(static)和实例(instance)的域与方法的JNI函数。每一个函数接受(做为参数)域或方法的类,它们的名称,符号和它们对应返回的jfieldID或jmethodID。 java
函数 | 描述 |
GetFieldID | 获得一个实例的域的ID |
GetStaticFieldID | 获得一个静态的域的ID |
GetMethodID | 获得一个实例的方法的ID |
GetStaticMethodID | 获得一个静态方法的ID |
构造一个Java对象的实例 android
jclass cls = (*env)->FindClass(env, "Lpackagename/classname;"); //建立一个class的引用 jmethodID id = (*env)->GetMethodID(env, cls, "", "(D)V"); //注意这里方法的名称是"",它表示这是一个构造函数,并且构造参数是double型的 jobject obj = (*env)->NewObjectA(env, cls, id, args); //得到一实例,args是构造函数的参数,它是一个jvalue*类型。
首先是得到一个Java类的class引用 (*env)->FindClass(env, "Lpackagename/classname;"); 请注意参数:Lpackagename/classname; ,L表明这是在描述一个对象类型,packagename/classname是该对象耳朵class路径,请注意必定要以分号(;)结束! c++
而后是获取函数的id,jmethodID id = env->GetMethodID(cls, "", "(D)V"); 第一个是刚刚得到的class引用,第二个是方法的名称,最后一个就是方法的签名了 数组
仍是不懂?我曾经如此,请接着看... 函数
JNINativeMethod的定义以下: spa
typedef struct { const char* name; const char* signature; void* fnPtr; } JNINativeMethod;第一个变量name是Java中函数的名字。
其中比较难以理解的是第二个参数,例如
"()V"
"(II)V"
"(Ljava/lang/String;Ljava/lang/String;)V" 指针
实际上这些字符是与函数的参数类型一一对应的。
"()" 中的字符表示参数,后面的则表明返回值。例如"()V" 就表示void Func();
"(II)V" 表示 void Func(int, int); code
类型
|
符号 |
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 (参数类型)返回类型 |
稍稍补充一下: 对象
一、方法参数或者返回值为java中的对象时,签名中必须以“L”加上其路径,不过此路径必须以“/”分开,自定义的对象也使用本规则 内存
好比说 java.lang.String为“java/lang/String”,com.nedu.jni.helloword.Student为"Lcom /nedu/jni/helloword/Student;"
二、方法参数或者返回值为数组类型时,请前加上[
例如[I表示 int[],[[[D表示 double[][][],即几维数组就加几个[
jclass cls = (*env)->GetObjectClass(env, obj); // 使用GetObjectClass方法获取obj对应的jclass。 jclass cls = (*env)->FindClass(“android/util/log”) // 直接搜索类名,须要是static修饰的类。
jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "(I)V"); //GetStaticMethodID(…),获取静态方法的ID使用GetMethdoID方法获取你要使用的方法的MethdoID其参数的意义:
(*env)->CallVoidMethod(env, obj, mid, depth);// CallStaticIntMethod(….) , 调用静态方法使用CallVoidMethod方法调用方法。参数的意义:
注:这里使用的是CallVoidMethod方法调用,由于没有返回值,若是有返回值的话使用对应的方法,在后面会提到。
CallVoidMethod CallStaticVoidMethod CallIntMethod CallStaticVoidMethod CallBooleanMethod CallStaticVoidMethod CallByteMethod CallStaticVoidMethod
如今稍稍明白文章开始构造Java对象那个实例了吧?让咱们继续深刻一下:
从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 */ jstring charToJstring(JNIEnv* env, const char* pat) { jclass strClass = (*env)->FindClass(env, "java/lang/String"); jmethodID ctorID = (*env)->GetMethodID(env, strClass, "", "([BLjava/lang/String;)V"); jbyteArray bytes = (*env)->NewByteArray(env, strlen(pat)); (*env)->SetByteArrayRegion(env, bytes, 0, strlen(pat), (jbyte*)pat); jstring encoding = (*env)->NewStringUTF(env, "UTF-8"); return (jstring)(*env)->NewObject(env, strClass, ctorID, bytes, encoding); } /* java jstring turn to c/c++ char* */ char* jstringToChar(JNIEnv* env, jstring jstr) { char* pStr = NULL; jclass jstrObj = (*env)->FindClass(env, "java/lang/String"); jstring encode = (*env)->NewStringUTF(env, "utf-8"); jmethodID methodId = (*env)->GetMethodID(env, jstrObj, "getBytes", "(Ljava/lang/String;)[B"); jbyteArray byteArray = (jbyteArray)(*env)->CallObjectMethod(env, jstr, methodId, encode); jsize strLen = (*env)->GetArrayLength(env, byteArray); jbyte *jBuf = (*env)->GetByteArrayElements(env, byteArray, JNI_FALSE); if (jBuf > 0) { pStr = (char*)malloc(strLen + 1); if (!pStr) { return NULL; } memcpy(pStr, jBuf, strLen); pStr[strLen] = 0; } env->ReleaseByteArrayElements(byteArray, jBuf, 0); return pStr; }
本文转自Zhiweiofli's Blog,转载请注明出处,谢谢。