Android 는 JNI 를 통 해 자바 류 의 구조 방법 과 부모 류 를 호출 하 는 방법

7053 단어 androidndkjni
Android 는 JNI 를 통 해 자바 클래스 의 구조 방법 을 호출 하여 자바 클래스 를 만 들 수 있 습 니 다.
구조 방법 을 호출 하 다.
구조 방법 을 호출 하 는 절 차 는 이전 호출 클래스 의 인 스 턴 스 방법 절차 와 유사 하 며 해당 하 는 클래스 와 방법 id 를 얻어 야 합 니 다.
클래스 에 대해 서 는 FindClass 를 통 해 해당 하 는 자바 형식 을 찾 을 수 있 습 니 다.
구조 방법 에 대해 서 는 방법 id 는 GetMethodID 방법 으로 얻 을 수 있 지만 구조 방법 에 대응 하 는 이름 은 반환 값 유형 은 void 형식 입 니 다.
상기 준비 조건 을 완성 하면 NewObject 을 통 해 구조 방법 을 호출 하여 구체 적 인 종 류 를 만 들 수 있다.
다음은 String 의 어떤 구조 방법 을 예 로 들 면
public String(char value[]) // Java String           

대응 하 는 C + + 코드:
extern "C"
JNIEXPORT jstring JNICALL
Java_com_glumes_cppso_jnioperations_InvokeConstructorOps_invokeStringConstructors(JNIEnv *env, jobject instance) {

    jclass stringClass;
    jmethodID cid;
    jcharArray elemArr;
    jstring result;

    //   C++         Java    
    jstring temp = env->NewStringUTF("this is char array");
    //    Java              ,   String        
    const jchar *chars = env->GetStringChars(temp, NULL);
    int len = 10;

    stringClass = env->FindClass("java/lang/String"); //       String  
    if (stringClass == NULL) {
        return NULL;
    }
    //        ,([C)V      String   String(char value[])     
    cid = env->GetMethodID(stringClass, "", "([C)V");
    if (cid == NULL) {
        return NULL;
    }
    //          
    elemArr = env->NewCharArray(len);
    if (elemArr == NULL) {
        return NULL;
    }
    //         
    env->SetCharArrayRegion(elemArr, 0, len, chars);
    //    
    result = (jstring) env->NewObject(stringClass, cid, elemArr);
    env->DeleteLocalRef(elemArr);
    env->DeleteLocalRef(stringClass);
    return result;
}

String 의 구조 함 수 는 문자 배열 을 전달 해 야 하기 때문에 먼저 문자 배열 을 구성 하고 값 을 부여 하 며 해당 하 는 클래스 와 방법 id 를 얻 은 후에 NewObject 방법 으로 호출 하면 됩 니 다.
사용자 정의 클래스 를 호출 하 는 구조 방법의 예 시 를 살 펴 보 겠 습 니 다. 이전 Animal 클래스 인지, 구조 방법 에는 String 형식의 인자 가 있 습 니 다.
/**
 *      Java   Animal     
 */
extern "C"
JNIEXPORT jobject JNICALL
Java_com_glumes_cppso_jnioperations_InvokeConstructorOps_invokeAnimalConstructors(JNIEnv *env, jobject instance) {
    jclass animalClass;
    jmethodID mid;
    jobject result;
    animalClass = env->FindClass("com/glumes/cppso/model/Animal");
    if (animalClass == NULL) {
        return NULL;
    }
    mid = env->GetMethodID(animalClass, "", "(Ljava/lang/String;)V");
    if (mid == NULL) {
        return NULL;
    }
    jstring args = env->NewStringUTF("this animal name");
    result = env->NewObject(animalClass, mid, args);
    env->DeleteLocalRef(animalClass);
    return result;
}

전체 호출 절 차 는 절차 에 따라 만 하면 된다 는 것 을 알 수 있다.
뉴 오 브 젝 트 방법 외 에 도 JNI 는 AllocObject 방법 으로 대상 을 만 들 고 같은 Animal 류 구조 방법 을 사용 하 는 것 을 예 로 들 었 다.
/**
 *    AllocObject         
 */
extern "C"
JNIEXPORT jobject JNICALL
Java_com_glumes_cppso_jnioperations_InvokeConstructorOps_allocObjectConstructor(JNIEnv *env, jobject instance) {
    jclass animalClass;
    jobject result;
    jmethodID mid;
    //        
    animalClass = env->FindClass("com/glumes/cppso/model/Animal");
    if (animalClass == NULL) {
        return NULL;
    }
    //        id
    mid = env->GetMethodID(animalClass, "", "(Ljava/lang/String;)V");
    if (mid == NULL) {
        return NULL;
    }
    //        
    jstring args = env->NewStringUTF("use AllocObject");
    //     ,              
    result = env->AllocObject(animalClass);
    if (result == NULL) {
        return NULL;
    }
    //    CallNonvirtualVoidMethod            
    env->CallNonvirtualVoidMethod(result, animalClass, mid, args);
    if (env->ExceptionCheck()) {
        env->DeleteLocalRef(result);
        return NULL;
    }
    return result;
}

마찬가지 로 필요 한 것 을 먼저 준비 해 야 한다.대응 하 는 유형의 유형, 방법 id, 구조 방법의 인 자 를 얻 습 니 다.
그리고 AllocObject 방법 으로 대상 을 만 듭 니 다. 그러나 주의해 야 할 것 은 이때 만 든 대상 은 초기 화 되 지 않 았 습 니 다. NewObject 방법 과 달리 만 든 대상 은 바로 초기 화 되 었 습 니 다. 어느 정도 에 AllocObject 방법 은 초기 화 지연 이 라 고 할 수 있 습 니 다.
다음은 CallNonvirtualVoidMethod 을 통 해 대응 하 는 구조 방법 을 호출 해 야 한다.이 곳 에 들 어 오 는 매개 변 수 는 jclass 형식 이 아니 라 초기 화 되 지 않 은 클래스 jobject 입 니 다.
이 방법 을 통 해 자바 의 클래스 를 만 들 수 있 습 니 다.
부류 호출 방법
JNI 를 통 해 부모 클래스 의 인 스 턴 스 방법 을 호출 할 수 있 습 니 다.
하위 클래스 에서 호출 CallNonvirtualMethod 방법 을 통 해 부모 클래스 를 호출 하 는 방법.
먼저, 해당 하 는 하위 클래스 를 구성 한 다음 에 부모 클래스 의 유형 과 방법 id 를 얻 고 해당 하 는 매개 변 수 를 준비 하 며 부모 클래스 방법의 반환 값 에 따라 서로 다른 CallNonvirtualMethod 함 수 를 호출 합 니 다.
인용 유형 에 대해 서 는 CallNonvirtual Object Method 방법 을 호출 합 니 다.기본 유형의 경우 CallNonvirtual BooleanMethod, CallNonvirtual IntMethod 등 을 호출 합 니 다.반환 값 이 없 는 형식 에 대해 서 는 CallNonvirtual Void Method 방법 을 호출 합 니 다.
구체 적 으로 코드 보기:
/**
 *        
 *       ,           
 */
extern "C"
JNIEXPORT void JNICALL
Java_com_glumes_cppso_jnioperations_InvokeConstructorOps_callSuperMethod(JNIEnv *env, jobject instance) {
    jclass cat_cls; // Cat     
    jmethodID cat_cid; // Cat        id
    jstring cat_name; // Cat         
    jobject cat;
    //        
    cat_cls = env->FindClass("com/glumes/cppso/model/Cat");
    if (cat_cls == NULL) {
        return;
    }
    //        id
    cat_cid = env->GetMethodID(cat_cls, "", "(Ljava/lang/String;)V");
    if (cat_cid == NULL) {
        return;
    }
    //          
    cat_name = env->NewStringUTF("this is cat name");
    //    Cat  
    cat = env->NewObject(cat_cls, cat_cid, cat_name);
    if (cat == NULL) {
        return;
    }
    //      getName   
    jclass animal_cls; //      
    jmethodID animal_mid; //           id
    //         
    animal_cls = env->FindClass("com/glumes/cppso/model/Animal");
    if (animal_cls == NULL) {
        return;
    }
    //            id
    animal_mid = env->GetMethodID(animal_cls, "getName", "()Ljava/lang/String;");
    if (animal_mid == NULL) {
        return;
    }
    jstring name = (jstring) env->CallNonvirtualObjectMethod(cat, animal_cls, animal_mid);
    if (name == NULL) {
        return;
    }
    LOGD("getName method value is %s", env->GetStringUTFChars(name, NULL));

    //          
    animal_mid = env->GetMethodID(animal_cls, "callInstanceMethod", "(I)V");
    if (animal_mid == NULL) {
        return;
    }
    env->CallNonvirtualVoidMethod(cat, animal_cls, animal_mid);
}

Cat 류 는 Animal 류 의 하위 클래스 로 서 먼저 NewObject 방법 으로 Cat 류 를 만 든 다음 부모 류 를 호출 하 는 방법 입 니 다.
이로써 JNI 를 통 해 자 바 를 호출 하 는 것 은 기본적으로 완 성 된 셈 이다.
구체 적 인 예시 코드 는 나의 Github 프로젝트 를 참고 할 수 있 습 니 다. 스타 를 환영 합 니 다.
https://github.com/glumes/AndroidDevWithCpp
위 챗 공식 번호 에 관심 을 가 져 주 셔 서 감사합니다.

좋은 웹페이지 즐겨찾기