JNI에서는 자바 원시 INT에 C 정수 매개 변수를 전달 할 수 있습니까?

zfgo :

나는 몇 가지 기본 방법에서 호출하고자하는 자바 방법이있다 :

    public void onDownloadProgress(int current, int total) {

    }

나는 네이티브 메소드에서 자바 메소드 위를 호출하는 것을 시도하고있다 :

    int current = ...
    int total = ...
    jni_callVoidMethod(
        env,
        jDownloadCallback,
        "onDownloadProgress",
        "(II)V",
        current,
        total
    );

jni_callVoidMethod는 헬퍼 방법과 그 구현은 다음과 같습니다

    void jni_callVoidMethod(JNIEnv *env, jobject receiver, const char *methodName, const char *contract, ...) {
        jclass clazz = env->GetObjectClass(receiver);
            if (NULL != clazz) {
            jmethodID method = env->GetMethodID(
            clazz,
            methodName,
            contract
        );
        if (NULL != method) {
            BUILD_VARARGS()
                env->CallVoidMethodV(
                receiver,
                method,
                va_args
            );
        if (env->ExceptionCheck()) { // prints out the exception if one is present
            env->ExceptionDescribe();
            env->ExceptionClear();
        }
        va_end(va_args);
        }
        env->DeleteLocalRef(clazz);
    }
}

그러나, Java 메소드에 나는 아주 이상한 INT 값을 얻고있다. 예를 들어, 3840120912. 내가 직접 정수 형태가 될 Java 메소드의 매개 변수를 선언하는 대신 자바 원시 INT에 C의 INT를 보낼 수 있습니다 궁금? 그 두 개의 매개 변수를 선언하는 것은 나를 위해 정수 작품이 될 나는 올바른 값을 얻고있다.

편집 :의 구현 BUILD_VARARGS 매크로 :

#define BUILD_VARARGS() \
va_list va_args; \
va_start(va_args, contract); \
const char *cur = contract; \
while ('\0' != *cur && '(' != *cur) { /* skip to opening paren */ \
    cur++; \
} \
while ('\0' != *cur && ')' != *cur) { /* stop at closing paren */ \
    switch (*cur) { \
        case 'Z': \
            va_arg(va_args, int); /* bool (unsigned 8-bit int) */ \
            break; \
        case 'B': \
            va_arg(va_args, int); /* byte (signed 8-bit int) */ \
            break; \
        case 'C': \
            va_arg(va_args, int); /* char (unsigned 16-bit int) */ \
            break; \
        case 'S': \
            va_arg(va_args, int); /* short (signed 16-bit int) */ \
            break; \
        case 'I': \
            va_arg(va_args, long long); /* int (signed 32-bit int) (must be passed in as a long long) */ \
            break; \
        case 'J': \
            va_arg(va_args, long); /* long (signed 64-bit int) */ \
            break; \
        case 'F': \
            va_arg(va_args, double); /* float (32 bits) */ \
            break; \
        case 'D': \
            va_arg(va_args, double); /* double (64 bits) */ \
            break; \
        case 'L': \
            /* fully-qualified-class */ \
            while (';' != *++cur && '\0' != *cur); /* advance to end of class declaration */ \
            /* FIXME breaks varargs, seems to not be needed va_arg(va_args, jobject); */ \
            break; \
        case '[': \
            /* TODO type type[] */ \
        case '(': \
            /* TODO ( arg-types ) ret-type  method type */ \
        default: \
            break; \
    } \
    cur++; \
}
몸부림 :

즉 모든 것을 설명! 귀하의 호출하는 va_arg인수를 소비 할 때 CallVoidMethodV그것을 얻을, 그것은 스택에 다른 곳에서 읽고 있습니다. 로부터 va_arg수동 :

va_arg를 () 호출의 다음 인수의 종류와 값을 갖는 식으로 매크로 확장한다. 파라미터는 AP에서 초기화하는 va_start의 va_list의 AP ()이다.
va_arg를 호출 할 때마다 ()을 수정 AP 통신 그래서 다음 호출이 반환 다음 인수가.

대신를 작성해야합니다 va_list즉시에 넘겨 CallVoidMethodV:

va_list va_args;
va_start(va_args, contract);
env->CallVoidMethodV(receiver, method, va_args);
va_end(va_args);

추천

출처http://10.200.1.11:23101/article/api/json?id=400855&siteId=1