Вызов метода Java из С++ в идентификаторе класса Android и идентификаторе метода

У меня проблемы с вызовом Java из моего собственного кода C. В частности, мне было трудно убедиться, что я получил правильные идентификаторы классов и методов. Сначала мне повезло со статическими методами, а не с функциями-членами, но я пробовал оба.

Как вы можете видеть ниже, простая логическая функция Java retTrue успешно возвращается, но я не могу правильно передать массив данных.

статический jmethodID midSetRTS, midClearRTS, midClearRTSb, midTX, midSniffRx, midSniffTx, midClose; статический jmethodID midgetFTDIDevice;

static JavaVM *g_VM;
static jclass cls;
static jmethodID javaMethodRef;


JNIEXPORT jstring JNICALL Java_com_example_rick_myjni_MyNDK_getMyString(JNIEnv *env, jobject jobj) {
    __android_log_print(ANDROID_LOG_VERBOSE, TAG, "Hello from native code");

    env->GetJavaVM(&g_VM);
    __android_log_print(ANDROID_LOG_VERBOSE, TAG, "Attaching to VM thread.");

    jint rs = g_VM->AttachCurrentThread((JNIEnv**)&env,NULL);
    if(rs == JNI_OK)
        __android_log_print(ANDROID_LOG_VERBOSE, TAG, "Attached");
    else
        __android_log_print(ANDROID_LOG_VERBOSE, TAG, "Failed to Attach");

    static int once = 1;
    if (once) {
        jclass dataClass = env->FindClass("com/example/rick/myjni/MainActivity");
        if (env->ExceptionCheck()) {
           return (*env).NewStringUTF("Exception");
        }

        cls = (jclass) env->NewGlobalRef(dataClass);
        if (env->ExceptionCheck()) {
           return (*env).NewStringUTF("Exception");
        }

        javaMethodRef = env->GetStaticMethodID(cls, "retTrue", "()Z");
        __android_log_print(ANDROID_LOG_VERBOSE, TAG, "cls: %d javaMethodRef %d", (int)cls, (int)javaMethodRef);
        midTX = env->GetStaticMethodID(cls, "TX", "([BI)Z");
        __android_log_print(ANDROID_LOG_VERBOSE, TAG, "cls: %d midTX %d", (int)cls, (int)midTX);

        if (env->ExceptionCheck()) {
           return (*env).NewStringUTF("Exception");
        }
        once = 0;
    }
    bool success = true;
    jbyte txTestMsg[] = {0x18, 0x00, 0x0D, 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0xFF,0x00,0xFF};
    jint len = 16;
    __android_log_print(ANDROID_LOG_VERBOSE, TAG, "len: %d txTestMsg: %x %x %x %x  %x %x %x %x  %x %x %x %x  %x %x %x %x ", len,
        txTestMsg[0], txTestMsg[1], txTestMsg[2], txTestMsg[3],
        txTestMsg[4], txTestMsg[5], txTestMsg[6], txTestMsg[7],
        txTestMsg[8], txTestMsg[9], txTestMsg[10], txTestMsg[11],
        txTestMsg[12], txTestMsg[13], txTestMsg[14], txTestMsg[15]);

    success = env->CallStaticBooleanMethod(cls, javaMethodRef);
    __android_log_print(ANDROID_LOG_VERBOSE, TAG, "Call retTrue succces: %d",success);

    COFFEE_TRY() {
        success = env->CallStaticBooleanMethod(cls, midTX, txTestMsg, len);
        if (env->ExceptionCheck()) {
               return (*env).NewStringUTF("Exception");
        }
    }
    COFFEE_CATCH() {
        coffeecatch_throw_exception(env);
    } COFFEE_END();

    if(success)
        return (*env).NewStringUTF("Success");
    else
        return (*env).NewStringUTF("Failure");
}

Из основной деятельности

 public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    ...

    public static boolean TX(byte[] data, int len)
    {
        Log.i(TAG,"MainActivity:TX length " + len + " data: " + data.toString() );
        return myFTDIdevice.TX(data,len);
    }

    public static boolean retTrue()
    {
        Log.i(TAG,"MainActivity:reTrue");
        return true;
    }

Обратите внимание на вывод из файла журнала Android:

08-17 14:55:49.827 12389-12432/com.example.rick.myjni V/MyJNI: Hello from native code
08-17 14:55:49.827 12389-12432/com.example.rick.myjni V/MyJNI: Attaching to VM thread.
08-17 14:55:49.827 12389-12432/com.example.rick.myjni V/MyJNI: Attached
08-17 14:55:49.827 12389-12432/com.example.rick.myjni V/MyJNI: cls: 1050382 javaMethodRef -2012626856
08-17 14:55:49.827 12389-12432/com.example.rick.myjni V/MyJNI: cls: 1050382 midTX -2012627024
08-17 14:55:49.827 12389-12432/com.example.rick.myjni V/MyJNI: len: 16 txTestMsg: 18 0 d 1  2 3 4 5  6 7 8 9  a ffffffff 0 ffffffff 
08-17 14:55:49.827 12389-12432/com.example.rick.myjni I/MainActivity: MainActivity:reTrue
08-17 14:55:49.827 12389-12432/com.example.rick.myjni V/MyJNI: Call retTrue succces: 1
08-17 14:55:49.832 12389-12432/com.example.rick.myjni A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0xdead4321 in tid 12432 (Thread-9233)
08-17 14:55:49.872 12389-12396/com.example.rick.myjni W/art: Suspending all threads took: 13.880ms
08-17 14:55:49.902 12389-12432/com.example.rick.myjni A/art: sart/runtime/check_jni.cc:65] JNI DETECTED ERROR IN APPLICATION: JNI NewStringUTF called with pending exception 'java.lang.Error' thrown in java.lang.String com.example.rick.myjni.MyNDK.getMyString():-2
08-17 14:55:49.902 12389-12432/com.example.rick.myjni A/art: sart/runtime/check_jni.cc:65]     in call to NewStringUTF
08-17 14:55:49.902 12389-12432/com.example.rick.myjni A/art: sart/runtime/check_jni.cc:65]     from java.lang.String com.example.rick.myjni.MyNDK.getMyString()
08-17 14:55:49.902 12389-12432/com.example.rick.myjni A/art: sart/runtime/check_jni.cc:65] "Thread-9233" prio=5 tid=16 Runnable
08-17 14:55:49.902 12389-12432/com.example.rick.myjni A/art: sart/runtime/check_jni.cc:65]   | group="main" sCount=0 dsCount=0 obj=0x12f7f7c0 self=0xb47c4800
08-17 14:55:49.902 12389-12432/com.example.rick.myjni A/art: sart/runtime/check_jni.cc:65]   | sysTid=12432 nice=0 cgrp=default sched=0/0 handle=0xb4509c00
08-17 14:55:49.902 12389-12432/com.example.rick.myjni A/art: sart/runtime/check_jni.cc:65]   | state=R schedstat=( 0 0 0 ) utm=6 stm=5 core=1 HZ=100
08-17 14:55:49.902 12389-12432/com.example.rick.myjni A/art: sart/runtime/check_jni.cc:65]   | stack=0x9ce0c000-0x9ce0e000 stackSize=1036KB
08-17 14:55:49.902 12389-12432/com.example.rick.myjni A/art: sart/runtime/check_jni.cc:65]   | held mutexes= "mutator lock"(shared held)
08-17 14:55:49.902 12389-12432/com.example.rick.myjni A/art: sart/runtime/check_jni.cc:65]   native: #00 pc 00004e6c  /system/lib/libbacktrace_libc++.so (UnwindCurrent::Unwind(unsigned int, ucontext*)+23)
08-17 14:55:49.902 12389-12432/com.example.rick.myjni A/art: sart/runtime/check_jni.cc:65]   native: #01 pc 00003665  /system/lib/libbacktrace_libc++.so (Backtrace::Unwind(unsigned int, ucontext*)+8)
08-17 14:55:49.902 12389-12432/com.example.rick.myjni A/art: sart/runtime/check_jni.cc:65]   native: #02 pc 00266509  /system/lib/libart.so (art::DumpNativeStack(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, int, char const*, art::mirror::ArtMethod*)+84)
08-17 14:55:49.902 12389-12432/com.example.rick.myjni A/art: sart/runtime/check_jni.cc:65]   native: #03 pc 0024857f  /system/lib/libart.so (art::Thread::Dump(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const+158)
08-17 14:55:49.902 12389-12432/com.example.rick.myjni A/art: sart/runtime/check_jni.cc:65]   native: #04 pc 000b4e83  /system/lib/libart.so (art::JniAbort(char const*, char const*)+610)
08-17 14:55:49.902 12389-12432/com.example.rick.myjni A/art: sart/runtime/check_jni.cc:65]   native: #05 pc 000b55a9  /system/lib/libart.so (art::JniAbortF(char const*, char const*, ...)+68)
08-17 14:55:49.902 12389-12432/com.example.rick.myjni A/art: sart/runtime/check_jni.cc:65]   native: #06 pc 000b8873  /system/lib/libart.so (art::ScopedCheck::ScopedCheck(_JNIEnv*, int, char const*)+1342)
08-17 14:55:49.902 12389-12432/com.example.rick.myjni A/art: sart/runtime/check_jni.cc:65]   native: #07 pc 000c1665  /system/lib/libart.so (art::CheckJNI::NewStringUTF(_JNIEnv*, char const*)+28)
08-17 14:55:49.902 12389-12432/com.example.rick.myjni A/art: sart/runtime/check_jni.cc:65]   native: #08 pc 0000162f  /data/app/com.example.rick.myjni-2/lib/arm/libMyLibrary.so (_JNIEnv::NewStringUTF(char const*)+10)
08-17 14:55:49.902 12389-12432/com.example.rick.myjni A/art: sart/runtime/check_jni.cc:65]   native: #09 pc 00001845  /data/app/com.example.rick.myjni-2/lib/arm/libMyLibrary.so (Java_com_example_rick_myjni_MyNDK_getMyString+516)
08-17 14:55:49.902 12389-12432/com.example.rick.myjni A/art: sart/runtime/check_jni.cc:65]   native: #10 pc 000162e7  /data/data/com.example.rick.myjni/cache/slice-slice_5-classes.dex (Java_com_example_rick_myjni_MyNDK_getMyString__+82)
08-17 14:55:49.902 12389-12432/com.example.rick.myjni A/art: sart/runtime/check_jni.cc:65]   at com.example.rick.myjni.MyNDK.getMyString(Native method)
08-17 14:55:49.902 12389-12432/com.example.rick.myjni A/art: sart/runtime/check_jni.cc:65]   at com.example.rick.myjni.MainActivity$3.run(MainActivity.java:150)
08-17 14:55:49.902 12389-12432/com.example.rick.myjni A/art: sart/runtime/check_jni.cc:65]   at java.lang.Thread.run(Thread.java:818)
08-17 14:55:49.902 12389-12432/com.example.rick.myjni A/art: sart/runtime/check_jni.cc:65] 

person Ben Payment    schedule 15.08.2016    source источник
comment
Когда вы печатаете приведение jclass к типу int, вы печатаете указатель на структуру, возвращенную из GetObjectClass. Вы не обязательно будете получать один и тот же результат каждый раз для одного и того же класса, поэтому указатели не будут совпадать. Кроме того, env->GetObjectClass(jobj); собирается вернуть класс myNDK, потому что это функция, для которой вызывается нативная функция, но функция, которую вы хотите вызвать, находится в MainActivity, отсюда и ошибка.   -  person samgak    schedule 16.08.2016
comment
Я пытался вызвать MID, полученный из каждой ссылки на cls в этом примере, и все они терпят неудачу. Я добавил статические вспомогательные методы в класс myNDK и попытался вызвать их. Также я не понимаю, почему, если они указывают на один и тот же класс, значение указателя не будет одинаковым (целое приведение).   -  person Ben Payment    schedule 17.08.2016


Ответы (1)


ОМГ, я хочу вышибить себе мозги. Это не имело ничего общего с идентификатором метода или идентификатором класса, но с передаваемыми аргументами. Мне пришлось создать действительный массив Java в C, чтобы его можно было передать.

   bool success = true;
    jbyte temptxTestMsg[] = {0x18, 0x00, 0x0D, 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0xFF,0x00,0xFF};
    jint len = 16;

    jbyteArray txTestMsg = env->NewByteArray(len);
    env->SetByteArrayRegion(txTestMsg,0,len,temptxTestMsg);
person Ben Payment    schedule 17.08.2016