Android-JNI-互调问题

对于这个方法参数中的JNIEnv* env参数的解释:

JNIEnv类型实际上代表了Java环境,通过这个JNIEnv* 指针,就可以对Java端的代码进行操作。例如,创建Java类中的对象,调用Java对象的方法,获取Java对象中的属性等等。JNIEnv的指针会被JNI传入到本地方法的实现函数中来对Java端的代码进行操作。

JNIEnv类中有很多函数可以用:

NewObject:创建Java类中的对象

NewString:创建Java类中的String对象

New<Type>Array:创建类型为Type的数组对象

Get<Type>Field:获取类型为Type的字段

Set<Type>Field:设置类型为Type的字段的值

GetStatic<Type>Field:获取类型为Type的static的字段

SetStatic<Type>Field:设置类型为Type的static的字段的值

Call<Type>Method:调用返回类型为Type的方法

CallStatic<Type>Method:调用返回值类型为Type的static方法

等许多的函数,具体的可以查看jni.h文件中的函数名称。

参数:jobject obj的解释:

如果native方法不是static的话,这个obj就代表这个native方法的类实例

如果native方法是static的话,这个obj就代表这个native方法的类的class对象实例(static方法不需要类实例的,所以就代表这个类的class对象)


此段属于cpp中语法,如果是c,所有方法的第一个参数需要加上env

GetXXXField/GetStaticXXXField简介
GetXXXField/GetStaticXXXField中的XXX表示对什么类型的Field进行操作。前者用于非静态Field,后者用于静态Field。
该系列函数包括:
非静态

  jobject GetObjectField (jobject obj0, jfieldID fld1)

  jboolean GetBooleanField (jobject obj0, jfieldID fld1)

  jbyte GetByteField (jobject obj0, jfieldID fld1)

  jchar GetCharField (jobject obj0, jfieldID fld1)

  jshort GetShortField (jobject obj0, jfieldID fld1)

  jint GetIntField (jobject obj0, jfieldID fld1)

  jlong GetLongField (jobject obj0, jfieldID fld1)

  jfloat GetFloatField (jobject obj0, jfieldID fld1)

  jdouble GetDoubleField (jobject obj0, jfieldID fld1)


静态

 jobject GetStaticObjectField (jclass cl0, jfieldID fld1)

 jboolean GetStaticBooleanField (jclass cl0, jfieldID fld1)

 jbyte GetStaticByteField (jclass cl0, jfieldID fld1)

 jchar GetStaticCharField (jclass cl0, jfieldID fld1)

 jshort GetStaticShortField (jclass cl0, jfieldID fld1)

 jint GetStaticIntField (jclass cl0, jfieldID fld1)

 jlong GetStaticLongField (jclass cl0, jfieldID fld1)

 jfloat GetStaticFloatField (jclass cl0, jfieldID fld1)

 jdouble GetStaticDoubleField (jclass cl0, jfieldID fld1)


第一个参数,jcalss cl0用于表示在哪个类上进行操作。
第二个参数,表示GetFieldID/GetStaticFieldID中得到的Field的id
SetXXXField/SetStaticXXXField简介
SetXXXField/SetStaticXXXField中的XXX表示对什么类型的Field进行操作。前者用于非静态Field,后者用于静态Field。
该系列函数包括:
非静态

  void SetObjectField (jobject obj0, jfieldID fld1, jobject obj2)

  void SetBooleanField (jobject obj0, jfieldID fld1, jboolean val2)

  void SetByteField (jobject obj0, jfieldID fld1, jbyte val2)

  void SetCharField (jobject obj0, jfieldID fld1, jchar val2)

  void SetShortField (jobject obj0, jfieldID fld1, jshort val2)

  void SetIntField (jobject obj0, jfieldID fld1, jint val2)

  void SetLongField (jobject obj0, jfieldID fld1, jlong val2)

  void SetFloatField (jobject obj0, jfieldID fld1, jfloat val2)

  void SetDoubleField (jobject obj0, jfieldID fld1, jdouble val2)

静态

 void SetStaticObjectField (jclass cl0, jfieldID fld1, jobject obj2)

  void SetStaticBooleanField (jclass cl0, jfieldID fld1, jboolean val2)

  void SetStaticByteField (jclass cl0, jfieldID fld1, jbyte val2)

  void SetStaticCharField (jclass cl0, jfieldID fld1, jchar val2)

  void SetStaticShortField (jclass cl0, jfieldID fld1, jshort val2)

  void SetStaticIntField (jclass cl0, jfieldID fld1, jint val2)

  void SetStaticLongField (jclass cl0, jfieldID fld1, jlong val2)

  void SetStaticFloatField (jclass cl0, jfieldID fld1, jfloat val2)

  void SetStaticDoubleField (jclass cl0, jfieldID fld1, jdouble val2)


第一个参数,jcalss cl0用于表示在哪个类上进行操作。
第二个参数,表示GetFieldID/GetStaticFieldID中得到的Field的id
第三个参数,表示新值
GetMethodID/GetStaticMethodID简介
jmethodID GetMethodID (jclass cl0, const char * val1, const char * val2)
jmethodID GetStaticMethodID (jclass cl0, const char * val1, const char * val2)
调用他们能得到函数的id(以jmethodID形式表示).前者用于非静态Field,后者用于静态Field
第一个参数,jcalss cl0用于表示在哪个类上进行操作。
第二个参数,const char * val对应函数的名字
第三个参数,const char * val2用于表示函数的传入参数都有哪些,都是些什么类型,返回参数是什么类型。因为函数可以重载,所以必须要该参数才能定为函数。这里是以符号的形式表示传入参数的类型。
关于java参数类型的符号化表示请参考《JNI中java类型的符号化表示》
CallXXXMethod/CallStaticXXXMethod
CallXXXMethod/CallStaticXXXMethod中的XXX表示对什么返回类型的Field函数进行调用。前者用于非静态函数的调用,后者用于静态函数的调用。
该系列函数包括:
非静态
 

 jobject CallObjectMethod (jobject obj0, jmethodID meth1, ...)

  jboolean CallBooleanMethod (jobject obj0, jmethodID meth1, ...)

  jbyte CallByteMethod (jobject obj0, jmethodID meth1, ...)

  jchar CallCharMethod (jobject obj0, jmethodID meth1, ...)

  jshort CallShortMethod (jobject obj0, jmethodID meth1, ...)

  jint CallIntMethod (jobject obj0, jmethodID meth1, ...)

  jlong CallLongMethod (jobject obj0, jmethodID meth1, ...)

  jfloat CallFloatMethod (jobject obj0, jmethodID meth1, ...)

  jdouble CallDoubleMethod (jobject obj0, jmethodID meth1, ...)

  void CallVoidMethod (jobject obj0, jmethodID meth1, ...)

静态

  jobject CallStaticObjectMethod (jclass cl0, jmethodID meth1, ...)

  jboolean CallStaticBooleanMethod (jclass cl0, jmethodID meth1, ...)

  jbyte CallStaticByteMethod (jclass cl0, jmethodID meth1, ...)

  jchar CallStaticCharMethod (jclass cl0, jmethodID meth1, ...)

  jshort CallStaticShortMethod (jclass cl0, jmethodID meth1, ...)

  jint CallStaticIntMethod (jclass cl0, jmethodID meth1, ...)

  jlong CallStaticLongMethod (jclass cl0, jmethodID meth1, ...)

  jfloat CallStaticFloatMethod (jclass cl0, jmethodID meth1, ...)

  jdouble CallStaticDoubleMethod (jclass cl0, jmethodID meth1, ...)

  void CallStaticVoidMethod (jclass cl0, jmethodID meth1, ...)


第一个参数,jobject obj0表示调用哪个对象的非静态函数;jcalss cl0表示调用哪个类的静态函数。
第二个参数,jmethodID meth1表示调用函数的id(以jmethodID形式进行表示)
第三个及以后的参数,他们是调用的java函数的传入参数

jobject     (*CallObjectMethod)(JNIEnv*, jobject, jmethodID, ...);
    jobject     (*CallObjectMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    jobject     (*CallObjectMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
    jboolean    (*CallBooleanMethod)(JNIEnv*, jobject, jmethodID, ...);
    jboolean    (*CallBooleanMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    jboolean    (*CallBooleanMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
    jbyte       (*CallByteMethod)(JNIEnv*, jobject, jmethodID, ...);
    jbyte       (*CallByteMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    jbyte       (*CallByteMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
    jchar       (*CallCharMethod)(JNIEnv*, jobject, jmethodID, ...);
    jchar       (*CallCharMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    jchar       (*CallCharMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
    jshort      (*CallShortMethod)(JNIEnv*, jobject, jmethodID, ...);
    jshort      (*CallShortMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    jshort      (*CallShortMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
    jint        (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...);
    jint        (*CallIntMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    jint        (*CallIntMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
    jlong       (*CallLongMethod)(JNIEnv*, jobject, jmethodID, ...);
    jlong       (*CallLongMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    jlong       (*CallLongMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
    jfloat      (*CallFloatMethod)(JNIEnv*, jobject, jmethodID, ...);
    jfloat      (*CallFloatMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    jfloat      (*CallFloatMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
    jdouble     (*CallDoubleMethod)(JNIEnv*, jobject, jmethodID, ...);
    jdouble     (*CallDoubleMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    jdouble     (*CallDoubleMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
    void        (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
    void        (*CallVoidMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    void        (*CallVoidMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);

问题1.返回String.

如果返回的是String,并且文件是c,不是cpp.

则需要(*env)->NewStringUTF(env,str)

JNIEXPORT jint JNICALL Java_test_test_test_ccx_com_testtesttest_Java2C_sort
  (JNIEnv *env, jobject instance, jint a, jint b ){

         jclass myclass = (*env)->FindClass(env,"test/test/test/ccx/com/testtesttest/Java2C");
         jmethodID mid = (*env)->GetMethodID(env,myclass,"show","(Ljava/lang/String;)V");
         (*env)->CallVoidMethod(env,instance,mid,(*env)->NewStringUTF(env,"adfsdvf"));

         return sort(a,b);
}

int sort(int a,int b ){
  return a+b;
}

 否则会报错.

    public native int sort( int a, int b);


    public void show(String msg) {
        Toast.makeText(mContext, msg, Toast.LENGTH_SHORT).show();
    }

问题2 Your project contains C++ files but it is not using a supported native build system. Consider using 

在module的gradle里面加入

    sourceSets {
        main {
            jni.srcDirs = []
            jniLibs.srcDirs = ['你的so路径']
        }
    }

在defaultConfig里面加入

        ndk {
            moduleName "moduleName"
            abiFilters "armeabi-v7a"
        }

然后在project的gradle里面加入

android.useDeprecatedNdk=true 

问题解决

猜你喜欢

转载自blog.csdn.net/ci250454344/article/details/84308663
今日推荐