jni应用(如何访问方法Java的类)

本文将通过实例来说明如何在jni 访问Java的类和成员。开始先介绍所有对象分类的方法,最后才是实例说明。

访问对象的属性和方法                  

1、实例属性的访问                 

  jfieldID  GetFieldID (JNIEnv*env, jclass clazz, const char *name, const char*sig);                

   功能:返回类的实例(非静态)域的属性 ID。该域由其名称及签名指定。访问器函数的Get<type>Field Set<type>Field

       系列使用域 ID检索对象域。GetFieldID()不能用于获取数组的长度域。应使用GetArrayLength()          

   参数  envJNI接口指针。            

               clazzJava类对象。            

              name:该属性的Name名称                

               sig  该属性的域签名。               

   返回值:属性ID。如果操作失败,则返回NULL              

   抛出 NoSuchFieldError:如果找不到指定的域。                  

             ExceptionInInitializerError:如果由于异常而导致类初始化程序失败。          

             OutOfMemoryError:如果系统内存不足。                 

   Get<type>Field例程               

  NativeType  Get<type>Field (JNIEnv*env, jobject obj, jfieldIDfieldID);                

    功能:该访问器例程系列返回对象的实例(非静态)域的值。要访问的域由通过调用GetFieldID()而得到的域 ID 指定。           

    参数   envJNI接口指针。            

                objJava对象(不能为 NULL)。               

                fieldID:有效的域 ID                 

   返回值   属性的内容。      

        Get<type>Field例程名        本地类型        

              GetObjectField()                 jobject     

               GetBooleanField()              jboolean  

              GetByteField()                    jbyte        

              GetCharField()                    jchar        

              GetShortField()                   jshort       

              GetIntField()                       jint  

              GetLongField()                    jlong         

              GetFloatField()                   jfloat        

               GetDoubleField()     jdouble    

   Set<type>Field 方法族 

  void  Set<type>Field (JNIEnv *env, jobject obj, jfieldIDfieldID,  NativeTypevalue);           

  功能该访问器例程系列设置对象的实例(非静态)属性的值。要访问的属性由通过调用SetFieldID()而得到的属性 ID指定。

   参数  envJNI接口指针。            

              objJava对象(不能为 NULL)。               

             fieldID:有效的域 ID                

              value:域的新值。   

     方法族 如下:                    

               Set<type>Field 方法族           本地类型        

                 SetObjectField()                   jobject     

                 SetBooleanField()                 jboolean  

                  SetByteField()                      jbyte        

                 SetCharField()                      jchar        

                 SetShortField()                    jshort       

                 SetIntField()                        jint  

                  SetLongField()                     jlong         

                 SetFloatField()                     jfloat        

                 SetDoubleField()                 jdouble    

 

 2、静态属性的访问 :也存在相同的方法,

       jfieldID  GetStaticFieldID (JNIEnv *env,jclass clazz, const char *name, const char*sig);     

       NativeType  GetStatic<type>Field (JNIEnv*env,jclass classzz , jfieldIDfieldID);           

            void  SetStatic<type>Field (JNIEnv *env,jclassclasszz, jfieldIDfieldID,  NativeTypevalue);           

   它们与实例属性的唯一区别在于第二个参数jclass classzz代表的是类引用,而不是类实例。

        

 3、调用实例方法 

  jmethodID GetMethodID(JNIEnv *env, jclass clazz,    const char*name, const char *sig);               

    功能:返回类或接口实例(非静态)方法的方法 ID。方法可在某个 clazz 的超类中定义,也可从 clazz继承。该方法由其名称

        和签名决定。 GetMethodID()可使未初始化的类初始化。要获得构造函数的方法 ID,应将 <init>作为方法名,同时将 

        void (V)作为返回类型。          

   参数  envJNI接口指针。            

               clazzJava类对象。            

               name:方法名。          

               sig:方法的签名。           

    返回值 方法 ID,如果找不到指定的方法,则为 NULL             

    抛出    NoSuchMethodError:如果找不到指定方法。            

                 ExceptionInInitializerError:如果由于异常而导致类初始化程序失败。          

                 OutOfMemoryError:如果系统内存不足。                  

 Call<type>Method例程  Call<type>MethodA例程  Call<type>MethodV例程 

 NativeType Call<type>Method (JNIEnv*en v,  jobject obj , jmethodIDmethodID, ...);     //参数附加在函数后面,              

 NativeType Call<type>MethodA (JNIEnv *env, jobject obj, jmethodID methodID,jvalue *args);  //参数以指针形式附加  

  NativeType Call<type>MethodV (JNIEnv *env, jobject obj,jmethodID methodID, va_listargs); //参数以"链表"形式附加

     

  说明:这三个操作的方法用于从本地方法调用Java实例方法。它们的差别仅在于向其所调用的方法传递参数时所用的机制。   

      这三个操作将根据所指定的方法 ID调用 Java 对象的实例(非静态)方法。参数 methodID必须通过调用 GetMethodID() 

      来获得。当这些函数用于调用私有方法和构造函数时,方法 ID必须从obj 的真实类派生而来,而不应从其某个超类派生。

      当然,附加参数可以为空

  参数  envJNI接口指针。            

            objJava对象。           

            methodID:方法 ID                 

  返回值 返回调用 Java方法的结果。              

  抛出  执行 Java方法时抛出的异常。    

             

  下表根据结果类型说明了各个方法类型。用户应将Call<type>Method中的 type 替换为所调用方法的Java 类型(或使用表

 中的实际方法名),同时将 NativeType替换为该方法相应的本地类型。省略掉了其他两种类型。 

Java层返回值             方法族                 本地返回类型NativeType

 返回值为void    CallVoidMethod()   A / V        ()

 返回值为引用类型:     CallObjectMethod( )                            jobect

 返回值为boolean    CallBooleanMethod ( )                         jboolean

 返回值为byte          CallByteMethod( )                                jbyte

 返回值char           CallCharMethod( )                               jchar

 返回值short          CallShortMethod()                              jshort       

 返回值为int            CallIntMethod()                                     jint  

 返回值为long    CallLongMethod()                             jlong        

 返回值为float   CallFloatMethod()                                 jfloat        

返回值为double    CallDoubleMethod()                          jdouble    

 

 4、调用静态方法:也存在如下方法群,

       jfieldID  GetStaticMethodID (JNIEnv *env,jclass clazz, const char *name, const char*sig);     

       NativeType  Call<type>Method (JNIEnv*env,jclass classzz , jfieldIDfieldID);      


实例如下:

Java 的类如下:

/***test class 需要测试的jni里访问的类********/

public class testTime{


  public int mVersion;

  private int year;
  private int month;
  private int day;
  private int hour;
  private int minute;
  private int second;
  private int reserved;


  public
    byte[] channelCdata = new byte[1024];


public testTime()

{

}

  public
    void setTdtDate(int mYear, int mMonth, int mDay)
    {
    this.year = mYear;
    this.month = mMonth;
    this.day = mDay;
    }
  public
    void setTdtTime(int mHour, int mMinute, int mSecond)
    {
    this.hour = mHour;
    this.minute = mMinute;
    this.second = mSecond;
    }


  public
    void SetCharArray(byte[] cData, int data_size)
    {
    if (data_size == 0) {
        return;
    }
    byte[] buffer = new byte[data_size];
    System.arraycopy(cData, 0, buffer, 0, data_size);
    String charText= new String(buffer);
    }


 public
    byte[] getCharArray()
    {
          String myNane = "gchen"
          byte[] charArray = myNane.getBytes();
          return charArray;
    }

}

/***************jni java class***********************/

package android.com.test;

public class jniTest{

   public
    native final int jni2JavaClass(Object objTestTime);

static
    {
        Log.i(TAG, "load testjni lib");
        System.loadLibrary("testjni");
    }

public jniTest()

{

}


public testJniCallJava()

{

 testTime mtim = newtestTime();

  jni2JavaClass((Object)mtim);

}

}


/***************jni cpp***********************/

static const char *classPathName = "android/com/test/jniTest";

static JNINativeMethod methods[] = {
    { "jni2JavaClass", "(Ljava/lang/Object;)I", (void *)android_com_test_jniTest_jni2JavaClass},
};

int android_com_test_jniTest_jni2JavaClassJNIEnv *env, jobject thiz,jobjectobjTestTime)

{

int ret = -1;

 jclass testTime= env->GetObjectClass(objTestTime);  /********获取Java的类引用*********/
  if (testTime== NULL) {
              return ret;
       }

jfieldID mfield = env->GetFieldID(testTime, "mVersion", "I");/**********获取Java的成员以及类型**************/

int version = env->GetIntField(objTestTime,mfield);/**********访问Java的成员,读取**************/

env->SetIntField(objTestTime,(jin)0x00) ;;/**********访问Java的成员,设置**************/


jmethodID mMethodld == env->GetMethodID(testTime, "setTdtDate", "(III)V");  /**********获取Java的方法以及类型**************/
env->CallVoidMethod(objTestTime,mMethodld, 2016, 01,01); /**********调用Java的方法**************/


mMethodld== env->GetMethodID(testTime, "setTdtTime", "(III)V");
env->CallVoidMethod(objTestTime,mMethodld, 9, 30,30);


 char mycontry[20] = "China"

 jbyteArray byteArray;
 jint cDataSize = strlen(mycontry);

 byteArray = env->NewByteArray(cDataSize);
 env->SetByteArrayRegion(byteArray, (jsize)0, (jsize)cDataSize, (jbyte *)mycontry);
 mMethodld = env->GetMethodID(testTime, "SetCharArray", "([BI)V");/**********获取Java的方法以及类型**************/
 env->CallVoidMethod(objTestTime, mMethodld,byteArray, cDataSize);  /**********访问Java的方法**************/
 env->DeleteLocalRef(byteArray);


  char myname[20] = "";

 mMethodld = env->GetMethodID(testTime, "getCharArray", "()[B"); /**********获取Java的方法以及类型**************/
 byteArray = (jbyteArray)env->CallObjectMethod(objTestTime, mMethodld);/**********访问Java的方法**************/
 jsize arrayLen = env->GetArrayLength(byteArray);
if (arrayLen > 0) {
        env->GetByteArrayRegion(byteArray, (jsize)0, (jsize)arrayLen, (jbyte *)myname);
 }
env->DeleteLocalRef(byteArray);


byte data[1024];

mfield = env->GetFieldID(testTime, "channelCdata", "[B"); /**********获取Java的成员以及类型**************/
    jbyteArray chCdata = (jbyteArray)env->GetObjectField(objTestTime, mfield);
    env->GetByteArrayRegion(chCdata, (jsize)0, (jsize)1024, (jbyte *)data);


 env->SetByteArrayRegion(chCdata, (jsize)0, (jsize)1024, (jbyte *)data);/**********访问Java的成员,设置**************/

}








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值