您的位置:首页 > 移动开发 > Android开发

Android:Java Native Interface入门

2011-12-29 15:39 85 查看
示例:

int size = (*env)->GetArrayLength(env, array); //获得数组array的长度 ,返回整型

jarray array = ((*env)->GetObjectArrayElement(env, array, i)); //获得对象数组array的元素i,

jint *pp = (*env)->GetIntArrayElements(env, (jintArray)array, 0 ); //获得整型数组array的元素0,返回指针jint*类型

(*env)->ReleaseIntArrayElements(env, (jintArray)array, pp,0 ); //释放整型数组array的元素pp,

(*env)->DeleteLocalRef(env,intArr); //释放内存 调用GetObjectArrayElement不需要释放,但用完需要调用DeleteLocalRef删除对应局部引用,如果作为返回值就不用删除。

在如下情况下,会用到类型之间的转换:

1java方法里面将参数传入本地方法;

2在本地方法里面创建java对象;

3在本地方法里面return结果给java程序。

JAVA类型与本地类型的对应关系:

Java类型    本地类型    字节(bit)

boolean     jboolean      8, unsigned

byte            jbyte              8

char           jchar             16, unsigned

short         jshort             16

int              jint                  32

long           jlong              64

float           jfloat              32 

double       jdouble        64

void            void               n/a

 java对象                  jobject

注意:在使用完你所转换之后的对象之后,必须调用ReleaseStringUTFChars方法,让JVM释放转换成UTF-8的string的对象的空间,

否则,JVM中会一直保存该对象,不会被垃圾回收器回收,导致内存溢出。

访问String的一些方法:

GetStringUTFChars     //将jstring转换成为UTF-8格式的char*

GetStringChars                //将jstring转换成为Unicode格式的char*

ReleaseStringUTFChars        //释放指向UTF-8格式的char*的指针

ReleaseStringChars          // 释放指向Unicode格式的char*的指针

NewStringUTF              //创建一个UTF-8格式的String对象

NewString               //创建一个Unicode格式的String对象

GetStringUTFLengt     //获取UTF-8格式的char*的长度

GetStringLength    // 获取Unicode格式的char*的长度

访问Array对象:

示例:

jintArray arr;

jsize len = (*env)->GetArrayLength(env, arr);    //1 获取数组的长度: 

jint *body = (*env)->GetIntArrayElements(env, arr, 0); // 2 获取指向arr数组元素0的指针

for (i=0; i<len; i++) {  sum += body[i];}          // 3  使用指针取出Array中的元素 
(*env)->ReleaseIntArrayElements(env, arr, body, 0); // 4释放数组元素的引用  提醒JVM回收arr数组元素的引用。

获取数组元素指针:

函数                                              数组类型

GetBooleanArrayElements      boolean

GetByteArrayElements              byte

GetCharArrayElements            char

GetShortArrayElements           short

GetIntArrayElements                  int

GetLongArrayElements             long

GetFloatArrayElements             float

GetDoubleArrayElements         double

释放数组元素指针:

函数                                                          数组类型

ReleaseBooleanArrayElements       boolean

ReleaseByteArrayElements               byte

ReleaseCharArrayElements              char

ReleaseShortArrayElements            short

ReleaseIntArrayElements                   int               

ReleaseLongArrayElements             long

ReleaseFloatArrayElements             float

ReleaseDoubleArrayElements          double

访问自定义Java对象数组

GetObjectArrayElement

SetObjectArrayElement

 访问Java对象

示例:
jclass cls = (*env)->GetObjectClass(env, obj);     // 1 获取你需要访问的Java对象的类: obj对应的jclass。

jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "(I)V");     // 2 获取你要使用的方法的MethdoID。

其参数的意义:

  env-----JNIEnv

  cls-----第一步获取的jclass

  "callback"-----要调用的方法名

  "(I)V"-----方法的Signature签名(见后面)

(*env)->CallVoidMethod(env, obj, mid, depth);      //3 使用CallVoidMethod方法调用方法。

参数的意义:

  env-----JNIEnv

  obj----通过本地方法穿过来的jobject

  mid----要调用的MethodID(即第二步获得的MethodID)

  depth----方法需要的参数(对应方法的需求,添加相应的参数)

方法的Signature签名

方法的Signature是由方法的参数和返回值的类型共同构成的,结构为:
"(argument-types)return-type"

其中Java程序中参数类型和其对应的值如下:

Signature签名           Java中的类型

Z                                 boolean

B                                byte

C                                char

S                               short

I                                 int

J                               long

F                               float

D                              double

L                                fully-qualified-class //L类名

[                                 type  //数组

V                                void

一个Java类的方法的Signature签名可以通过javap命令获取:
javap -s -p Java类名

给调用的函数传参数:

通常我们直接在methodID后面将要传的参数添加在后面,但是还有其他的方法也可以传参数:

CallVoidMethodV                //获取一个数量可变的列表作为参数;

CallVoidMethodA              //获取一个union。

调用静态方法:

就是将第二步和第三步调用的方法改为对应的:

jmethodID GetStaticMethodID         //获取对应的静态方法的ID

CallStaticIntMethod                   // 调用静态方法

调用超类的方法:

CallNonvirtual<TYPE>Method

env->CallNonvirtualVoidMethod(p,clazz_Father,id_Father_function);          //调用父类方法 

访问Java对象的属性:

访问Java对象的属性和访问Java对象的方法基本上一样,只需要将函数里面的Method改为Field即可.

示例:

jclass objectClass = (env)->FindClass("com/sundy/jnidemo/DiskInfo");       //获得JAVA中的实例类

jfieldID fieldID = env->GetFieldID(native_clazz,"name","Ljava/lang/String;");      //获得域的ID

jint number= env->GetIntField(obj,fieldID);      //获得域属性

env->SetIntField(obj,fieldID,18880L) ;     //设置

不相关的额外函数:

char* jstringToWindows( JNIEnv *env, jstring jstr ); //将jstring类型转换成windows类型

jstring WindowsTojstring( JNIEnv* env, char* str ); //将windows类型转换成jstring类型

//将jstring类型转换成windows类型

char* jstringToWindows( JNIEnv *env, jstring jstr )

{

int length = (env)->GetStringLength(jstr );

const jchar* jcstr = (env)->GetStringChars(jstr, 0 );

char* rtn = (char*)malloc( length*2+1 );

int size = 0;

size = WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)jcstr, length, rtn,(length*2+1), NULL, NULL );

if( size <= 0 )

return NULL;

(env)->ReleaseStringChars(jstr, jcstr );

rtn[size] = 0;

return rtn;

}

//将windows类型转换成jstring类型

jstring WindowsTojstring( JNIEnv* env, char* str )

{

jstring rtn = 0;

int slen = strlen(str);

unsigned short * buffer = 0;

if( slen == 0 )

rtn = (env)->NewStringUTF(str );

else

{

int length = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, NULL, 0 );

buffer = (unsigned short *)malloc( length*2 + 1 );

if( MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, (LPWSTR)buffer, length ) >0 )

rtn = (env)->NewString( (jchar*)buffer, length );

}

if( buffer )

free( buffer );

return rtn;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息