jni 基本接口函数

来源:互联网 发布:ubuntu时间不对 编辑:程序博客网 时间:2024/05/25 21:32
说明:1. env参数是指向函数的列表的指针。在C中调用为(*env)->,在C++中调用为(env)->
      2. 本地方法的obj 的意义取决于该方法是静态还是实例方法(static or an instance method)。
         当本地方法作为一个实例方法时,第二个参数相当于对象本身,即this. 当本地方法作为一个静态方法时,
         指向所在类。
      3. java中的String不管是中文还是英文,一个字符总是对应两个字节
      4. Unicode 对应两个字节编码
      5. UTF8对应一个字节编码
      6. 变量的定义
        typedef long            jint;
     typedef __int64         jlong;
     typedef signed char     jbyte;
  typedef unsigned char     jboolean;
     typedef unsigned short     jchar;
     typedef short          jshort;
     typedef float          jfloat;
     typedef double          jdouble;
     typedef jint            jsize;
     
    

     
     
#define JNI_FALSE 0
#define JNI_TRUE 1
--------------------------字符系列----------------------------------------------------------
1、
函数原型:const char* (JNICALL *GetStringUTFChars)(JNIEnv *env, jstring str, jboolean *isCopy)
函数说明:用来取得某个jstring对象相关的Java字符串,把一个Unicode字串转成UTF-8格式字串
参数说明:jstring str:传入一个指向java中的String对象的jstring变量,
          jboolean *isCopy:传入一个jboolean的指针,是用来标识是否对java的String对象进行了拷贝。
          如果传入这个jboolean指针不是NULL,则它会给该指针所指向的内存传入JNI_TRUE或JNI_FALSE标
          识是否进行了拷贝。传入NULL表示不关心是否拷贝字符串,它就不会给jboolean*指向的内存赋值。
          一般会把isCopy设为NULL,不关心Java VM对返回的指针是否直接指向java.lang.String的内容。
          一般不能预知VM是否会拷贝java.lang.String的内容,程序员应该假设GetStringChars会为
          java.lang.String分配内存。在JavaVM的实现中,垃圾回收机制会移动对象,并为对象重新配置
          内存。一但java.lang.String占用的内存暂时无法被GC重新配置,将产生内存碎片,过多的内存碎
          片,会更频繁的出现内存不足的假象。
返回类型:char*
2、
函数原型:void (JNICALL *ReleaseStringUTFChars)(JNIEnv *env, jstring str, const char* chars);
函数说明:来释放拷贝的内容
参数说明: jstring str 指定一个jstring变量,即是要释放的本地字符串的来源,
           const char* chars 就是要释放的本地字符串

3、
函数原型:const jchar *(JNICALL *GetStringChars)(JNIEnv *env, jstring str, jboolean *isCopy);
函数说明:用来取得某个jstring对象相关的Java字符串,以Unicode形式存储
参数说明: 参数和GetStringUTFChars函数参数意思一样
返回类型:jchar 两个字节

4、
函数原型:void (JNICALL *ReleaseStringChars)(JNIEnv *env, jstring str, const jchar *chars);
函数说明:同ReleaseStringUTFChars
参数说明: 同ReleaseStringUTFChars
返回类型:void

5、
函数原型:jsize (JNICALL *GetStringLength)(JNIEnv *env, jstring str);
函数说明:获得以Unicode编码的字串长度
参数说明: jstring str Java 传进来的字符串对象
返回类型:Java中String对象中字符的个数
6、
函数原型: jsize (JNICALL *GetStringUTFLength)(JNIEnv *env, jstring str);
函数说明:获得以UTF8编码的字串长度
参数说明: jstring str Java 传进来的字符串对象
返回类型:Java中String对象中字符的个数


7、
函数原型:void GetStringUTFRegion(JNIEnv *env,jstring str, jsize start, jsize len, char *buf)
函数说明:拷贝Java字符串并以UTF-8编码传入buffer。把java字符串的内容直接拷贝到C/C++的字符数组中。
          在呼叫这个函数之前必须有一个C/C++分配出来的字符串,然后传入到这个函数中进行字符串的拷贝(此函数不分配内存)
参数说明:jstring str Java 传进来的字符串对象
          jsize start Java 传进来的字符串对象复制的起始地址
          jsize len 复制的数据长度
          char *buf 存放数据的buf
返回类型:void

8、
函数原型:void GetStringRegion(JNIEnv *env,jstring str, jsize start,jsize len,jchar* buffer);
函数说明:拷贝java字符串并以UTF-16编码传入buffer
函数说明:同GetStringUTFRegion
参数说明: 同GetStringUTFRegion
返回类型:void


9、
函数原型:jstring NewString(JNIEnv *env,const jchar* str,jsize len);
函数说明:在C/C++本地代码中创建JAVA的String字符串对象
参数说明:const jchar* str 在C中创建的jstring对象
          jsize len 组建字符的长度值,从0开始组建
返回类型:jstring

10、
函数原型:jstring NewStringUTF(const char * str);
函数说明:在C/C++本地代码中创建JAVA的String字符串对象
参数说明:const char* str 在C中创建的jstring对象
          jsize len 组建字符的长度值,从0开始组建
返回类型:jstring


以上函数所用实例:


C语言实现:

JNIEXPORT jstring JNICALL Java_com_tz_test_NativeTest_getCountFromC
  (JNIEnv * env , jclass obj,jstring str)
  {


  const jchar* getStr = (*env)->GetStringChars(env,str,JNI_FALSE);
  LOGI("getStrData==%s",getStr);
  jsize strSize = (*env)->GetStringLength(env,str);
  LOGI("getStrData==%d",strSize);
  (*env)->ReleaseStringChars(env,str,getStr);
 

  const char *getCStr = (*env)->GetStringUTFChars(env,str,JNI_FALSE);
  LOGI("getCStrData==%s",getCStr);
  jsize strCSize = (*env)->GetStringUTFLength(env,str);
  LOGI("getCStrData==%d",strCSize);
  (*env)->ReleaseStringUTFChars(env,str,getCStr);
 
  char outBuf [10] ;
  (*env)->GetStringUTFRegion(env,str,0,10,outBuf);
  LOGI("getOutCStrData==%s",outBuf);
 
  jchar outJBuf[10];
  (*env)->GetStringRegion(env,str,0,10,outJBuf);

 

  jstring jstr = (*env)->NewString(env,getStr,5);

const char * cjstring = "getstringfromC";
jstr = (*env)->NewStringUTF(env,cjstring);
  return jstr;
  }

         
         
  

//-----------------------------数组系列-----------------------------------------------------------------------------

1、
函数原型:jbyte * (JNICALL *GetByteArrayElements)(JNIEnv *env, jbyteArray array, jboolean *isCopy);
函数说明  将Java中的byte数组转换成JNI中的基本类型,并由该类型的指针指向第一个元素
参数说明:jbyteArray array,Java中的byte数组
          jboolean *isCopy 同字符函数的isCopy
返回类型  jbyte *

2、
函数原型:void (JNICALL *ReleaseByteArrayElements)(JNIEnv *env, jbyteArray array, jbyte *elems, jint mode)
函数说明:释放分配的jbyte数组
参数说明:jbyteArray array  Java中的byte数组
          jbyte *elems 由GetByteArrayElements函数分配的空间
          jint mode 释放模式 一般给0
         
3、
函数原型:jsize (JNICALL *GetArrayLength)(JNIEnv *env, jarray array);
函数说明:获得数组元素的个数
参数说明:jarray array  Java数组的对象
返回类型: jsize 数组元素个数

4、
函数原型:void (JNICALL *GetByteArrayRegion)(JNIEnv *env, jbyteArray array, jsize start, jsize len, jbyte *buf);
函数说明:将jbyteArray数组拷贝到buf中
参数说明:jbyteArray array 生成的jbyteArray 数组,可以使Java传递的,也可以使jni中自己生成
          jsize start  jbyteArray数组的起始地址
          jsize 要拷贝的数据长度
          jbyte buf 待存放数据的 jbyte buf
返回类型  void   

5、
函数原型:void (JNICALL *SetByteArrayRegion)(JNIEnv *env, jbyteArray array, jsize start, jsize len, jbyte *buf);
函数说明:将 buf数组中的值拷贝到jbyteArray数组中
参数说明:jbyteArray array 生成的jbyteArray 数组,可以使Java传递的,也可以使jni中自己生成
          jsize start  jbyteArray数组的起始地址, 从buf的首地址开始复制
          jsize 要拷贝的数据长度
          jbyte buf 待存放数据的 jbyte buf
返回类型  void      

6、
函数原型:jbyteArray (JNICALL *NewByteArray)(JNIEnv *env, jsize len);
函数说明:生成一个jbyteArray型数组(一维数组)
参数说明:jsize len 生成数组的大小
返回类型:jbyteArray 数组

7、还有其它类型生成的一维数组
1> jbooleanArray (JNICALL *NewBooleanArray)(JNIEnv *env, jsize len);
2> jbyteArray (JNICALL *NewByteArray)(JNIEnv *env, jsize len);
3> jcharArray (JNICALL *NewCharArray)(JNIEnv *env, jsize len);
4> jshortArray (JNICALL *NewShortArray)(JNIEnv *env, jsize len);
5> jintArray (JNICALL *NewIntArray)(JNIEnv *env, jsize len);
6> jlongArray (JNICALL *NewLongArray)(JNIEnv *env, jsize len);
7> jfloatArray (JNICALL *NewFloatArray)(JNIEnv *env, jsize len);
8> jdoubleArray (JNICALL *NewDoubleArray)(JNIEnv *env, jsize len);
9> jobjectArray (JNICALL *NewObjectArray)(JNIEnv *env, jsize len, jclass clazz, jobject init);

实例:

JNIEXPORT jstring JNICALL Java_com_tz_test_NativeTest_getCountFromC
  (JNIEnv * env , jclass obj,jstring str,jbyteArray bdata)
  {
  jint i = 0 ;    

  jbyte *jByte = (*env)->GetByteArrayElements(env,bdata,NULL);
 
 
  jsize len = (*env)->GetArrayLength(env,bdata);
 
  LOGI("arrary len = %d",len);
  unsigned char *cBuf  = (unsigned char *)malloc(len);
 
  memset(cBuf,0,len);
  memcpy(cBuf,jByte,len);
 
  jbyte *buf = (jbyte * )malloc(len);
 
   //另外一种方法
(*env)->GetByteArrayRegion(env,bdata,0,len,buf);
 
 
 
  jbyteArray byteBuf = (*env)->NewByteArray(env,len);
 
  (*env)->SetByteArrayRegion(env,byteBuf,2,len-5,buf);
  jByte = (*env)->GetByteArrayElements(env,byteBuf,NULL);
 
  for(i = 0 ; i < len; i++)
  {
       LOGI("%d",jByte[i]);
  }
   
   
   
  (*env)->ReleaseByteArrayElements(env, bdata, jByte, 0);


  const char * cjstring = "getstringfromC";
  jstring jstr = (*env)->NewStringUTF(env,cjstring);
  return jstr;
  }

还有和jbyteArray一样的其它类型的数组,用法一致


jbooleanArray
jbyteArray
jcharArray
jshortArray
jintArray
jlongArray
jfloatArray
jdoubleArray
jobjectArray


 
//------------------------------在jni中调用Java中的方法的函数------------------------------------------


类型签名:

签名是一种用参数个数和类型区分同名方法的手段,即解决方法重载问题。
其中要特别注意的是:
1. 类描述符开头的'L'与结尾的';'必须要有 String类型的签名是“Ljava/lang/String;”
2. 数组描述符,开头的'['必须有.
3. 方法描述符规则: "(各参数描述符)返回值描述符",其中参数描述符间没有任何分隔
符号



    类型签名  Java类型      C类型
     V      void            void
     Z      jboolean     boolean
     I      jint              int
     J      jlong            long
     D      jdouble       double
     F      jfloat            float
     B      jbyte            byte
     C      jchar           char
     S      jshort          short
    
           数组则以"["开始,用两个字符表示
     [I       jintArray      int[]
     [F     jfloatArray    float[]
     [B     jbyteArray    byte[]
     [C    jcharArray    char[]
     [S    jshortArray   short[]
     [D    jdoubleArray double[]
     [J     jlongArray     long[]
     [Z    jbooleanArray boolean[]

1、
函数原型:jclass (JNICALL *GetObjectClass)(JNIEnv *env, jobject obj);
函数说明:函数得到该对像的类,该函数返回一个jclass类型值,其中obj参数表示要你想要得到类型的类对象。通过该方法可以获取到调用该方法的对象所在的类
参数说明:见开头
返回类型:jclass
2、
函数原型:jclass (JNICALL *FindClass)(JNIEnv *env, const char *name);
函数说明:功能同GetObjectClass,但是在访问静态域的时候必须使用FindClass,而不能使用GetObjectClass。
           在FindClass()的第二个参数是类的编码签名,类的编码签名和 基本类型的编码签名有所不同,
           如果类在当前包中,就直接是类的名称,如果类不在当前包中则要加入该类的详细路径:
           例如String类在java.lang 包中,则String的签名要写成( Ljava/lang/String;),
           其中的(L和;)是不可少的,其中(;)是表达是的终止符
参数说明:const char *name:类全名(即包名后跟类名,之间由“/”分隔)。如果该名称以“[”(数组签名字符)打头,则返回一个一维数组类。
返回类型:jclass
3、
函数原型:jfieldID (JNICALL *GetFieldID)(JNIEnv *env, jclass clazz, const char *name, const char *sig);
函数说明:获取实例域的ID
参数说明:const char *name Java中定义的实例域的名称
           const char *sig  实例域的类型签名
           jclass clazz 获取到的类
返回类型:jfieldID
4、
函数原型:jobject (JNICALL *GetObjectField)(JNIEnv *env, jobject obj, jfieldID fieldID);
函数说明:获取到域ID的内容,Java的String类型,要用GetObjectField函数获取,这里提示大家没有
           GetStringField这样的函数在JNI中,或者说在C语言中
参数说明:jfieldID fieldID 有效的域ID
           jobject obj  Java中传下来的类对象
返回类型:域内容
5、
函数原型:jint (JNICALL *GetIntField)(JNIEnv *env, jobject obj, jfieldID fieldID);
函数说明:获取整型实例域的内容
参数说明:jfieldID fieldID 有效的域ID
           jobject obj  Java中传下来的类对象
返回类型:jint

6、还有其它类型的获取实例域的内容函数用法和GetIntField方法使用一样,
1> jboolean (JNICALL *GetBooleanField)(JNIEnv *env, jobject obj, jfieldID fieldID);
2> jbyte (JNICALL *GetByteField)(JNIEnv *env, jobject obj, jfieldID fieldID);
3> jchar (JNICALL *GetCharField)(JNIEnv *env, jobject obj, jfieldID fieldID);
4> jshort (JNICALL *GetShortField)JNIEnv *env, jobject obj, jfieldID fieldID);
5> jlong (JNICALL *GetLongField)(JNIEnv *env, jobject obj, jfieldID fieldID);
6> jfloat (JNICALL *GetFloatField)(JNIEnv *env, jobject obj, jfieldID fieldID);
7> jdouble (JNICALL *GetDoubleField)(JNIEnv *env, jobject obj, jfieldID fieldID);


7、
函数原型:jfieldID (JNICALL *GetStaticFieldID)(JNIEnv *env, jclass clazz, const char *name, const char *sig);
函数说明:获取静态域ID
参数说明:同GetFieldID
返回类型:jfieldID

8、
函数原型:jbyte (JNICALL *GetStaticByteField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
函数说明:获取静态域的数值
参数说明:jclass clazz FindClass函数获取到的Class,注意: 不是obj
           fieldID fieldID 同GetIntField
返回类型:jbyte
9、还有其它类型获取静态实例域的函数,使用方法同GetStaticByteField

    1> jobject (JNICALL *GetStaticObjectField)(JNIEnv *env, jclass clazz, jfieldID fieldID); //jstring
    2> jboolean (JNICALL *GetStaticBooleanField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
    3> jchar (JNICALL *GetStaticCharField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
    4> jshort (JNICALL *GetStaticShortField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
    5> jint (JNICALL *GetStaticIntField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
    6> jlong (JNICALL *GetStaticLongField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
    7> jfloat (JNICALL *GetStaticFloatField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
    8> jdouble (JNICALL *GetStaticDoubleField)(JNIEnv *env, jclass clazz, jfieldID fieldID);

10、
函数原型:void (JNICALL *SetObjectField)(JNIEnv *env, jobject obj, jfieldID fieldID, jobject val);  
函数说明:设置fieldID对应获取的实例域的新值(非静态),此函数针对jstring
参数说明:jfieldID fieldID,有效的域ID
           jobject val ,域的新值
返回类型:void

12、
函数原型:void (JNICALL *SetByteField)(JNIEnv *env, jobject obj, jfieldID fieldID, jbyte val); 
函数说明:设置字节型的实例域(非静态)
参数说明:同SetObjectField
返回类型:void
13、还有其它类型的设置实例域的方法使用方法和SetByteField一样
  
  
   1> void (JNICALL *SetBooleanField)(JNIEnv *env, jobject obj, jfieldID fieldID, jboolean val);   
   2> void (JNICALL *SetCharField)(JNIEnv *env, jobject obj, jfieldID fieldID, jchar val);
   3> void (JNICALL *SetShortField)(JNIEnv *env, jobject obj, jfieldID fieldID, jshort val);
   4> void (JNICALL *SetIntField)(JNIEnv *env, jobject obj, jfieldID fieldID, jint val);
   5> void (JNICALL *SetLongField)(JNIEnv *env, jobject obj, jfieldID fieldID, jlong val);
   6> void (JNICALL *SetFloatField)(JNIEnv *env, jobject obj, jfieldID fieldID, jfloat val);
   7> void (JNICALL *SetDoubleField)(JNIEnv *env, jobject obj, jfieldID fieldID, jdouble val);
  
14、
函数原型:void (JNICALL *SetStaticByteField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jbyte value);
函数说明:设置fieldID对应获取的实例域的新值(静态)
参数说明:jclass clazz,FindClass获取到的cla
返回类型:void

15、还有其它类型的设置静态实例域的方法使用方法和SetStaticByteField一样

1> void (JNICALL *SetStaticObjectField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value);
2> void (JNICALL *SetStaticBooleanField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jboolean value);
3> void (JNICALL *SetStaticCharField) (JNIEnv *env, jclass clazz, jfieldID fieldID, jchar value);
4> void (JNICALL *SetStaticShortField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jshort value);
5> void (JNICALL *SetStaticIntField) (JNIEnv *env, jclass clazz, jfieldID fieldID, jint value);
6> void (JNICALL *SetStaticLongField)   (JNIEnv *env, jclass clazz, jfieldID fieldID, jlong value);
7> void (JNICALL *SetStaticFloatField)  (JNIEnv *env, jclass clazz, jfieldID fieldID, jfloat value);
8> void (JNICALL *SetStaticDoubleField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble value);

以上方法使用的实例如下:

JNIEXPORT jstring JNICALL Java_com_tz_test_NativeTest_getCountFromC
  (JNIEnv * env , jclass obj,jstring str,jbyteArray bdata)
  {
//jstring claPath = "com/tz/test/NativeTest";


const char * cjstring = "new String";
jstring jstr = (*env)->NewStringUTF(env,cjstring);


// const char *cClaPath = (*env)->GetStringUTFChars(env,claPath,NULL);
  jclass cls = (*env)->FindClass(env,"com/tz/test/NativeTest");
//jclass cls = (*env)->GetObjectClass(env,obj);
if(cls == NULL)
{
     return NULL;
}
//获取实例域String    
jfieldID mfieldid = (*env)->GetFieldID(env,cls,"data","Ljava/lang/String;");
(*env)->SetObjectField(env,obj,mfieldid,jstr);
jstring getfieldValue = (jstring)(*env)->GetObjectField(env,obj,mfieldid);
const char *display = (*env)->GetStringUTFChars(env,getfieldValue,NULL);
LOGI("GET CLASS STRING FIELD VALUE  == %s",display);


//获取实例域INT
mfieldid = (*env)->GetFieldID(env,cls,"mInt","I");
jint getInt = (*env)->GetIntField(env,obj,mfieldid);
LOGI("GET CLASS INT FIELD VALUE == %d",getInt);

//获取byte实例域
jbyte mbyte = 45;
mfieldid = (*env)->GetFieldID(env,cls,"mByte","B");
(*env)->SetByteField(env,obj,mfieldid,mbyte);
jbyte getByte = (*env)->GetByteField(env,obj,mfieldid);
LOGI("GET CLASS BYTE FIELD VALUE == %d",getByte);

 
//获取静态的byte实例域 必须使用findclass函数
mfieldid = (*env)->GetStaticFieldID(env,cls,"staByte","B");
(*env)->SetStaticByteField(env,cls,mfieldid,(jbyte)65);
jbyte getStaByte = (*env)->GetStaticByteField(env,cls,mfieldid);
LOGI("GET CLASS STATIC BYTE FIELD VALUE == %d",getStaByte);

(*env)->ReleaseStringUTFChars(env,getfieldValue,display);
  return NULL;
  }



//--------------------------------访问Java中的方法-------------------------------------------------

1、
函数原型:jmethodID (JNICALL *GetMethodID)(JNIEnv *env, jclass clazz, const char *name, const char *sig);
函数说明: 获取方法的ID
参数说明:jclass clazz, 执行FindClass或者是getObjectClass函数返回的jclass类型
           const char *name, Java定义的方法名称
           const char *sig, 参数的签名
返回类型:jmethodID       


2、
函数原型:jint (JNICALL *CallIntMethod) (JNIEnv *env, jobject obj, jmethodID methodID, ...);
函数说明:调用Java中的方法(非静态)
参数说明:jmethodID methodID,调用方法的ID
           ...该方法的参数
返回类型:jnit

3、还有其它返回类型调用Java中的方法的函数
1> jobject (JNICALL *CallObjectMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...); //调用返回类型是jstring
2> jboolean (JNICALL *CallBooleanMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
3> jbyte (JNICALL *CallByteMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
4> jchar (JNICALL *CallCharMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
5> jshort (JNICALL *CallShortMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
6> jint (JNICALL *CallIntMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
7> jlong (JNICALL *CallLongMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
8> jfloat (JNICALL *CallFloatMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
9> jdouble (JNICALL *CallDoubleMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
10> void (JNICALL *CallVoidMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);

4、
函数原型:jmethodID (JNICALL *GetStaticMethodID)(JNIEnv *env, jclass clazz, const char *name, const char *sig);
函数说明:获得Java中定义的静态的方法的ID
参数说明:同GetMethodID
返回类型:同GetMethodID

5、
函数原型:jobject (JNICALL *CallStaticObjectMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, ...);
函数说明:调用静态的返回类型为String 的方法
参数说明: 同CallIntMethod
返回类型:jobject

6、还有其它返回类型调用Java中的静态方法
1> jobject (JNICALL *CallStaticObjectMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...); //调用返回类型是jstring
2> jboolean (JNICALL *CallStaticBooleanMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
3> jbyte (JNICALL *CallStaticByteMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
4> jchar (JNICALL *CallStaticCharMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
5> jshort (JNICALL *CallStaticShortMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
6> jint (JNICALL *CallStaticIntMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
7> jlong (JNICALL *CallStaticLongMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
8> jfloat (JNICALL *CallStaticFloatMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
9> jdouble (JNICALL *CallStaticDoubleMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
10> void (JNICALL *CallStaticVoidMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);

方法调用示例:

JNIEXPORT jstring JNICALL Java_com_tz_test_NativeTest_getCountFromC
  (JNIEnv * env , jclass obj,jstring str,jbyteArray bdata)
  {
//jstring claPath = "com/tz/test/NativeTest";


const char * cjstring = "new String";
jstring jstr = (*env)->NewStringUTF(env,cjstring);


// const char *cClaPath = (*env)->GetStringUTFChars(env,claPath,NULL);
  jclass cls = (*env)->FindClass(env,"com/tz/test/NativeTest");
//jclass cls = (*env)->GetObjectClass(env,obj);
if(cls == NULL)
{
     return NULL;
}

jmethodID mid = (*env)->GetMethodID(env,cls,"getResult","(II)I");    

jint x = 4;
jint y = 9;

jint getInt = (*env)->CallIntMethod(env,obj,mid,x,y);

LOGI("GET INT VALUE FROM METHOD = %d",getInt);

mid =  (*env)->GetStaticMethodID(env,cls,"getStr","(II)Ljava/lang/String;");
jstring getstr = (*env)->CallStaticObjectMethod(env,cls,mid,6,9);
const char *display = (*env)->GetStringUTFChars(env,getstr,NULL);
LOGI("GET CLASS StATIC STRING METHOD VALUE  == %s",display);
  (*env)->ReleaseStringUTFChars(env,getstr,display);
  return NULL;
  }
 
//---------------------------------其它常用函数介绍------------------------------------------
1、
函数原型:jobjectArray (JNICALL *NewObjectArray)(JNIEnv *env, jsize len, jclass clazz, jobject init);
函数说明:构造新的数组,它将保存类clazz中的对象。所有元素初始值均设为init。就是说此函数是建立保存类
           对象的数组,保存的对象类型为clazz。
参数说明:jsize len,数组的长度,对于Java中定义的多维数组在jni中显示为jobjectArray
           jclass clazz、数组保存的对象类型
           jobject init、数组的初始值
返回类型:jobjectArray        

2、
函数原型:void DeleteLocalRef(JNIEnv *env,jobject obj)     
函数说明:删除obj所指向的局部引用
参数说明:jobject obj,局部引用
返回类型:void

3、
函数原型:void SetObjectArrayElement(JNIEnv *env,jobjectArray array, jsize index,jobject val)
函数说明:设置Object数组的元素
参数说明:jobjectArray array,Java数组(可以是多维数组)
           jsize index, 数组下标
           jobject val, 数组新值,可以使一个值,也可以是一个数组
返回类型:void 

4、
函数原型: void SetIntArrayRegion(JNIEnv *env,jintArray array, jsize start, jsize len,const jint *buf)    
函数说明: 将基本类型数组的某一区域从缓冲区中复制回来的一组函数
参数说明: jintArray array,  java数组
            jsize start,Java数组的起始地址
            jsize len,要复制数组的长度
            const jint *buf,数据缓存区
返回类型: void


上述方法使用的一个实例:

java中定义
public  native byte[][] getCountFromC(String str,byte data[]);

C中定于
 
JNIEXPORT jobjectArray JNICALL Java_com_tz_test_NativeTest_getCountFromC
  (JNIEnv * env , jclass obj,jstring str,jbyteArray bdata)
  {

    jobjectArray result;
    jint i = 0;
    jint j = 0 ;
    jbyte temp [7]= {0,1,2,3,4,5,6};
   
    jclass byte_class = (*env)->FindClass(env,"[B");//建立对象数组
   
    if(byte_class == NULL)
    {
         return NULL;
    }
    else
    {
         result = (*env)->NewObjectArray(env,3,byte_class,NULL);
    }
    LOGI("Create byte_class Success");
    for(i = 0 ; i < 3 ; i++)
    {
         jbyteArray bytebuf = (*env)->NewByteArray(env,4);
       
        for(j = 0 ; j < 4; j ++)
        {
             temp[j] = i * j;
        }
   
        
         (*env)->SetByteArrayRegion(env,bytebuf,0,4,temp);
         (*env)->SetObjectArrayElement(env,result,i,bytebuf);
         (*env)->DeleteLocalRef(env,bytebuf);
    }
   
    return result;
  }

//-------------------------------------------------------------------------------------------- 
//-------------------------------------------------------------------------------------------- 
//-------------------------------------------------------------------------------------------- 
//-------------------------------------------------------------------------------------------- 
//-------------------------------------------------------------------------------------------- 
//-------------------------------------------------------------------------------------------- 


在本地代码中访问JNI

使用对象

JNI提供的另外一个功能是在本地代码中使用Java对象。通过使用合适的JNI函数,你可以创建Java对象,get、set 静态(static)和实例(instance)的域,调用静态(static)和实例(instance)函数。JNI通过ID识别域和方法,一个域或 方法的ID是任何处理域和方法的函数的必须参数。

表C列出了用以得到静态(static)和实例(instance)的域与方法的JNI函数。每个函数接受(作为参数)域或方法的类,它们的名称,符号和它们对应返回的jfieldID或jmethodID。

表C

函数描述GetFieldID得到一个实例的域的IDGetStaticFieldID得到一个静态的域的IDGetMethodID得到一个实例的方法的IDGetStaticMethodID得到一个静态方法的ID

※域和方法的函数

如果你有了一个类的实例,它就可以通过方法GetObjectClass得到,或者如果你没有这个类的实例,可以通过FindClass得到。符号是从域的类型或者方法的参数,返回值得到字符串,如表D所示。

表D

Java 类型符号booleanZbyteBcharCshortSintIlongLfloatFdoubleDvoidVobjects对象Lfully-qualified-class-name;L类名Arrays数组[array-type [数组类型methods方法(argument-types)return-type(参数类型)返回类型

※确定域和方法的符号

一旦你有了类和方法或者域的ID,你就能把它保存下来以后使用,而没有必要重复去获取。

有几个分别访问域和方法的函数。实例的域可以使用对应域的GetXXXField的变体函数访问。GetStaticXXXField函数用于静态类型。设置域的值,用SetXXXField 和SetStaticXXXField函数。表E包含了所有访问域的函数列表。

表E

Java 类型Method方法booleanGetBooleanField, GetStaticBooleanField, SetBooleanField,SetStaticBooleanFieldbyteGetByteField, GetStaticByteField, SetByteField, SetStaticByteFieldcharGetCharField, GetStaticCharField, SetCharField, SetStaticCharFieldshortGetShortField, GetStaticShortField, SetShortField, SetStaticShortFieldintGetIntField, GetStaticIntField, SetIntField, SetStaticIntFieldlongGetLongField, GetStaticLongField, SetLongField, SetStaticLongFieldfloatGetFloatField, GetStaticFloatField, SetFloatField, SetStaticFloatFielddoubleGetDoubleField, GetStaticDoubleField, SetDoubleField, SetStaticDoubleFieldobjectGetObjectField, GetStaticObjectField, SetObjectField, SetStaticObjectField

※访问域的函数

另外,方法的访问是由CallXXXMethod 函数和CallStaticXXXMethod函数完成的,XXX表明了方法的返回值类型。这些函数的变体允许传递数组参数 (CallXXXMethodA and CallStaticXXXMethodA)或者传递一个可变大小的列表(CallXXXMethodV and CallStaticXXXMethodV)。


一个完整的列表

表F:一个完整的列表

返回类型函数booleanCallBooleanMethod, CallBooleanMethodA, CallBooleanMethodV, CallStaticBooleanMethod, CallStaticBooleanMethodA, CallStaticBooleanMethodVbyteCallByteMethod, CallByteMethodA, CallByteMethodV, CallStaticByteMethod, CallStaticByteMethodA, CallStaticByteMethodVcharCallCharMethod, CallCharMethodA, CallCharMethodV, CallStaticCharMethod, CallStaticCharMethodA, CallStaticCharMethodVshortCallShortMethod, CallShortMethodA, CallShortMethodV, CallStaticShortMethod, CallStaticShortMethodA, CallStaticShortMethodVintCallIntMethod, CallIntMethodA, CallIntMethodV, CallStaticIntMethod, CallStaticIntMethodA, CallStaticIntMethodVlongCallLongMethod, CallLongMethodA, CallLongMethodV, CallStaticLongMethod, CallStaticLongMethodA, CallStaticLongMethodVfloatCallFloatMethod, CallFloatMethodA, CallFloatMethodV, CallStaticFloatMethod, CallStaticFloatMethodA, CallStaticFloatMethodVdoubleCallDoubleMethod, CallDoubleMethodA, CallDoubleMethodV, CallStaticDoubleMethod, CallStaticDoubleMethodA, CallStaticDoubleMethodVvoidCallVoidMethod, CallVoidMethodA, CallVoidMethodV, CallStaticVoidMethod, CallStaticVoidMethodA, CallStaticVoidMethodVobjectCallObjectMethod, CallObjectMethodA, CallObjectMethodV, CallStaticObjectMethod, CallStaticObjectMethodA, CallStaticObjectMethodV

※方法访问函数

清单E演示了如何在本地代码中调用方法。本地方法printRandom得到了静态方法Math.random的ID,并且调用它几次,打印出结果。实例方法也一样处理。

1 0
原创粉丝点击