JNI学习之---用jni API 访问java对象的属性,方法,调用构造器。

jni学习毕竟:

访问类对象的属性:

env 为 JNIEnv,obj的类型为jobject

JAVA_FieldAccessDemo_accessField(JNIEnv *env,jobject obj){
     
     jfieldID fid;
     jclass cls = (*env)->GetObjectClass(env, obj);
     //类FieldAccessDemo中有个String类型的属性s
     
     //获取要访问的属性的id
     fid = (*env)->GetFieldID(evn,cls,"s","Ljava/lang/String;");
    //读取属性值
    jstring jstr = (*env)->GetObjectField(env,obj,fid);
    char* str  = (*evn)->GetStringUTFChars(env,jstr,NULL);
   
    //释放资源
   (*env)->ReleaseStringUTFChars(env,jstr,str);

    //现在反过来,改变调用该本地方法的java对象的属性值
    jstr = (*env)->NewStringUTF(env,"88888");
    (*env)->SetObjectField(env,obj,fid,jstr);

}

总结:
  1.
   jfieldID fid = (*env)->GetFieldID(env,对象所属的类的jclass,
            属性名,
            属性对应的属性描述符号);
2.(*env)->GetObjectField(env,对象,属性id);

访问静态属性:
  假如有个类如下:

 class StaticFielcdAccess {
       private static int si;
       private native void accessField();
 }

那么实现为:

  JNIEXPORT void JNICALL
   Java_StaticFieldAccess_accessField(JNIEnv *env, jobject obj)
   {

       jfieldID fid;   /* store the field ID */
       jint si;
       jclass cls = (*env)->GetObjectClass(env, obj);   //获取类class
       fid = (*env)->GetStaticFieldID(env, cls, "si", "I");  //获取静态属性id
       si = (*env)->GetStaticIntField(env, cls, fid);   //读去属性的值
      (*env)->SetStaticIntField(env, cls, fid, 200);  //设置静态属性的值
   }



通过jni怎么去调用java层的类的实例方法和静态方法呢?

**************************1.访问实例方法**************************
假如有个这样的类:
 class InstanceMethodCall {
       private native void nativeMethod();
       private void callback() {
           System.out.println("In Java");
       }
       public static void main(String args[]) {
           InstanceMethodCall c = new InstanceMethodCall();
           c.nativeMethod();
} static {
           System.loadLibrary("InstanceMethodCall");
       }
}
jni实现:

JNIEXPORT void JNICALL
   Java_InstanceMethodCall_nativeMethod(JNIEnv *env, jobject obj)
   {
       //1.拿到class
       jclass cls = (*env)->GetObjectClass(env, obj);                         
       //2.拿到方法id
       jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "()V");           
        //3.根据obj,和方法id 调用方法
      (*env)->CallVoidMethod(env, obj, mid);   
   }

根据方法的返回值来决定调用哪个方法:
    Call<Type>Method
如果返回int  那么最后一步就调用  (*env)->CallIntMethod(env,obj,mid);


最后那个参数 "()V"   是方法描述符:

(I)V   带一个int 类型的参数,返回值类型为void
()D     没有参数,返回double   //注意!!没有参数并不是  (V)D

方法public static void main(String[] args) 对应的方法描的符为:

  ([Ljava/lang/String;)V

完整的方法描述符规则,http://java.sun.com/docs/books/jni/   12.3.4章节

**************************2.访问静态方法**************************
jclass cls = (*env)->GetObjectClass(env, obj);
jmethodID mid =
           (*env)->GetStaticMethodID(env, cls, "callback", "()V");
(*env)->CallStaticVoidMethod(env, cls, mid);    //注意,这里跟访问实例方法的区别是 第二个参数不是obj,而是cls


**************************3.访问父类的方法,怎么搞?**************************
传当前调用对象obj,父类class,方法id
CallNonvirtualVoidMethod,

**************************4.怎么用jni API 来调用 java层的构造器?**************************
我们来看在linphone中它是怎么调用Android 里面的AudioRecord类的构造器的->

查看android API
 http://developer.android.com/reference/android/media/AudioRecord.html
AudioRecord的构造器声明为:
AudioRecord(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes)


在linphone源码库的submodules/linphone/mediastreamer2/src/msandroid.cpp的方法sound_read_setup中有这么一段代码:
 static void sound_read_setup(MSFilter *f){
  //...
  jmethodID constructor_id=0;
     //...
     JNIEnv *jni_env = ms_get_jni_env();

  //这里是拿到类AudioRecord对应的class
     d->audio_record_class = (jclass)jni_env->NewGlobalRef(jni_env->FindClass("android/       media/AudioRecord"));
   //构造方法毕竟还是构造方法,所以,思路肯定是要先拿到构造方法对应的methodId
   //调用构造方法时,按调用实例方法的形式来调,只是第二个参数不再是构造方面名,而是<init>
      //因为类AudioRecord的构造方法有5个int类型参数,所以第三个参数 为 (IIIII)V

   constructor_id = jni_env->GetMethodID(d->audio_record_class,"<init>", "(IIIII)V");
 
   //构造方法的methodId 拿到了那就可以创建对象了:
   
    d->audio_record =  jni_env->NewObject(d->audio_record_class
            ,constructor_id
            ,1/*MIC*/
            ,d->rate
            ,2/*CHANNEL_CONFIGURATION_MONO*/
            ,2/*  ENCODING_PCM_16BIT */
            ,d->buff_size);




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值