Superpowered NDK Android: возврат int преуспевает в "внешнем" блоке, завершается с ошибкой в ​​вызываемой функции

Я пытаюсь выяснить, как вернуть int в Java из функции C++.

На стороне Java у меня есть следующее в кнопке. Я поместил его в кнопку, чтобы убедиться, что приложение было полностью загружено, прежде чем пытаться выполнить returnInt().

int testInt;
testInt = returnInt();
Log.i(TAG, "testInt");
Log.i(TAG, String.valueOf(testInt));

А также

private native int returnInt();

На стороне C++, возвращая int в extern блок успешен:

extern "C" JNIEXPORT jint Java_com_superpowered_crossexample_MainActivity_returnInt(JNIEnv * __unused javaEnvironment, jobject __unused obj) {
    return 50;
}

Но попытка следующего не удалась с SIGILL:

jint SuperpoweredExample::returnInt() {
__android_log_print(ANDROID_LOG_VERBOSE, "CrossExample ", "returnInt");  // this runs
    return 50;  // This fails with SIGILL
}

extern "C" JNIEXPORT jint Java_com_superpowered_crossexample_MainActivity_returnInt(JNIEnv * __unused javaEnvironment, jobject __unused obj) {
 // fails with SIGILL
    example->returnInt();
}

Любая идея, почему вышеизложенное приведет к SIGILL?

Я тестирую с помощью клона проекта CrossExample, предоставленного Superpowered. (Я просто использовал CrossExample как простой способ создать работающий проект Superpowered.)

Мой проект здесь:

https://github.com/mhurwicz/myCrossExample

Эта попытка вернуть int находится в myCrossExample1 ветка моего проекта.

Если по какой-либо причине вы этого хотели, оригинальный проект Superpowered находится здесь:

https://github.com/superpoweredSDK/Low-Latency-Android-Audio-iOS-Audio-Engine

Вот отладочный вывод:

Signal = SIGILL (signal SIGILL: illegal instruction operand)
javaEnvironment = {JNIEnv * | 0xb40d9a80} 0xb40d9a80
 [0] = {JNIEnv} 
  functions = {const JNINativeInterface * | 0xb4032a40} 0xb4032a40
   [0] = {const JNINativeInterface} 
    reserved0 = {void * | 0x0} nil
    reserved1 = {void * | 0x0} nil
    reserved2 = {void * | 0x0} nil
    reserved3 = {void * | 0x0} nil
    GetVersion = {jint (*)(JNIEnv *) | 0xb3a505f5} (libart.so`art::CheckJNI::GetVersion(_JNIEnv*))
    DefineClass = {jclass (*)(JNIEnv *, const char *, jobject, const jbyte *, jsize) | 0xb3a51ad0} (libart.so`art::CheckJNI::DefineClass(_JNIEnv*, char const*, _jobject*, signed char const*, int))
    FindClass = {jclass (*)(JNIEnv *, const char *) | 0xb3a51f8c} (libart.so`art::CheckJNI::FindClass(_JNIEnv*, char const*))
    FromReflectedMethod = {jmethodID (*)(JNIEnv *, jobject) | 0xb3a52c2f} (libart.so`art::CheckJNI::FromReflectedMethod(_JNIEnv*, _jobject*))
    FromReflectedField = {jfieldID (*)(JNIEnv *, jobject) | 0xb3a531b4} (libart.so`art::CheckJNI::FromReflectedField(_JNIEnv*, _jobject*))
    ToReflectedMethod = {jobject (*)(JNIEnv *, jclass, jmethodID, jboolean) | 0xb3a536f0} (libart.so`art::CheckJNI::ToReflectedMethod(_JNIEnv*, _jclass*, _jmethodID*, unsigned char))
    GetSuperclass = {jclass (*)(JNIEnv *, jclass) | 0xb3a523d8} (libart.so`art::CheckJNI::GetSuperclass(_JNIEnv*, _jclass*))
    IsAssignableFrom = {jboolean (*)(JNIEnv *, jclass, jclass) | 0xb3a527f0} (libart.so`art::CheckJNI::IsAssignableFrom(_JNIEnv*, _jclass*, _jclass*))
    ToReflectedField = {jobject (*)(JNIEnv *, jclass, jfieldID, jboolean) | 0xb3a53b50} (libart.so`art::CheckJNI::ToReflectedField(_JNIEnv*, _jclass*, _jfieldID*, unsigned char))
    Throw = {jint (*)(JNIEnv *, jthrowable) | 0xb3a53fb0} (libart.so`art::CheckJNI::Throw(_JNIEnv*, _jthrowable*))
    ThrowNew = {jint (*)(JNIEnv *, jclass, const char *) | 0xb3a544c0} (libart.so`art::CheckJNI::ThrowNew(_JNIEnv*, _jclass*, char const*))
    ExceptionOccurred = {jthrowable (*)(JNIEnv *) | 0xb3a549da} (libart.so`art::CheckJNI::ExceptionOccurred(_JNIEnv*))
    ExceptionDescribe = {void (*)(JNIEnv *) | 0xb3a54dd0} (libart.so`art::CheckJNI::ExceptionDescribe(_JNIEnv*))
    ExceptionClear = {void (*)(JNIEnv *) | 0xb3a55200} (libart.so`art::CheckJNI::ExceptionClear(_JNIEnv*))
    FatalError = {void (*)(JNIEnv *, const char *) | 0xb3a55a30} (libart.so`art::CheckJNI::FatalError(_JNIEnv*, char const*))
    PushLocalFrame = {jint (*)(JNIEnv *, jint) | 0xb3a55e3e} (libart.so`art::CheckJNI::PushLocalFrame(_JNIEnv*, int))
    PopLocalFrame = {jobject (*)(JNIEnv *, jobject) | 0xb3a5625d} (libart.so`art::CheckJNI::PopLocalFrame(_JNIEnv*, _jobject*))
    NewGlobalRef = {jobject (*)(JNIEnv *, jobject) | 0xb3a56bd5} (libart.so`art::CheckJNI::NewGlobalRef(_JNIEnv*, _jobject*))
    DeleteGlobalRef = {void (*)(JNIEnv *, jobject) | 0xb3a572d9} (libart.so`art::CheckJNI::DeleteGlobalRef(_JNIEnv*, _jobject*))
    DeleteLocalRef = {void (*)(JNIEnv *, jobject) | 0xb3a5729f} (libart.so`art::CheckJNI::DeleteLocalRef(_JNIEnv*, _jobject*))
    IsSameObject = {jboolean (*)(JNIEnv *, jobject, jobject) | 0xb3a57740} (libart.so`art::CheckJNI::IsSameObject(_JNIEnv*, _jobject*, _jobject*))
    NewLocalRef = {jobject (*)(JNIEnv *, jobject) | 0xb3a56b9b} (libart.so`art::CheckJNI::NewLocalRef(_JNIEnv*, _jobject*))
    EnsureLocalCapacity = {jint (*)(JNIEnv *, jint) | 0xb3a57313} (libart.so`art::CheckJNI::EnsureLocalCapacity(_JNIEnv*, int))
    AllocObject = {jobject (*)(JNIEnv *, jclass) | 0xb3a57b90} (libart.so`art::CheckJNI::AllocObject(_JNIEnv*, _jclass*))
    NewObject = {jobject (*)(JNIEnv *, jclass, jmethodID, ...) | 0xb3a5867c} (libart.so`art::CheckJNI::NewObject(_JNIEnv*, _jclass*, _jmethodID*, ...))
    NewObjectV = {jobject (*)(JNIEnv *, jclass, jmethodID, va_list) | 0xb3a580a5} (libart.so`art::CheckJNI::NewObjectV(_JNIEnv*, _jclass*, _jmethodID*, char*))
    NewObjectA = {jobject (*)(JNIEnv *, jclass, jmethodID, jvalue *) | 0xb3a586a7} (libart.so`art::CheckJNI::NewObjectA(_JNIEnv*, _jclass*, _jmethodID*, jvalue*))
    GetObjectClass = {jclass (*)(JNIEnv *, jobject) | 0xb3a58c7e} (libart.so`art::CheckJNI::GetObjectClass(_JNIEnv*, _jobject*))
    IsInstanceOf = {jboolean (*)(JNIEnv *, jobject, jclass) | 0xb3a59090} (libart.so`art::CheckJNI::IsInstanceOf(_JNIEnv*, _jobject*, _jclass*))
    GetMethodID = {jmethodID (*)(JNIEnv *, jclass, const char *, const char *) | 0xb3a599b0} (libart.so`art::CheckJNI::GetMethodID(_JNIEnv*, _jclass*, char const*, char const*))
    CallObjectMethod = {jobject (*)(JNIEnv *, jobject, jmethodID, ...) | 0xb3a6a042} (libart.so`art::CheckJNI::CallObjectMethod(_JNIEnv*, _jobject*, _jmethodID*, ...))
    CallObjectMethodV = {jobject (*)(JNIEnv *, jobject, jmethodID, va_list) | 0xb3a69fd9} (libart.so`art::CheckJNI::CallObjectMethodV(_JNIEnv*, _jobject*, _jmethodID*, char*))
    CallObjectMethodA = {jobject (*)(JNIEnv *, jobject, jmethodID, jvalue *) | 0xb3a67197} (libart.so`art::CheckJNI::CallObjectMethodA(_JNIEnv*, _jobject*, _jmethodID*, jvalue*))
    CallBooleanMethod = {jboolean (*)(JNIEnv *, jobject, jmethodID, ...) | 0xb3a69f6f} (libart.so`art::CheckJNI::CallBooleanMethod(_JNIEnv*, _jobject*, _jmethodID*, ...))
    CallBooleanMethodV = {jboolean (*)(JNIEnv *, jobject, jmethodID, va_list) | 0xb3a69f05} (libart.so`art::CheckJNI::CallBooleanMethodV(_JNIEnv*, _jobject*, _jmethodID*, char*))
    CallBooleanMethodA = {jboolean (*)(JNIEnv *, jobject, jmethodID, jvalue *) | 0xb3a6712d} (libart.so`art::CheckJNI::CallBooleanMethodA(_JNIEnv*, _jobject*, _jmethodID*, jvalue*))
    CallByteMethod = {jbyte (*)(JNIEnv *, jobject, jmethodID, ...) | 0xb3a69e9b} (libart.so`art::CheckJNI::CallByteMethod(_JNIEnv*, _jobject*, _jmethodID*, ...))
    CallByteMethodV = {jbyte (*)(JNIEnv *, jobject, jmethodID, va_list) | 0xb3a69e31} (libart.so`art::CheckJNI::CallByteMethodV(_JNIEnv*, _jobject*, _jmethodID*, char*))
    CallByteMethodA = {jbyte (*)(JNIEnv *, jobject, jmethodID, jvalue *) | 0xb3a670c3} (libart.so`art::CheckJNI::CallByteMethodA(_JNIEnv*, _jobject*, _jmethodID*, jvalue*))
    CallCharMethod = {jchar (*)(JNIEnv *, jobject, jmethodID, ...) | 0xb3a69dc7} (libart.so`art::CheckJNI::CallCharMethod(_JNIEnv*, _jobject*, _jmethodID*, ...))
    CallCharMethodV = {jchar (*)(JNIEnv *, jobject, jmethodID, va_list) | 0xb3a69d5d} (libart.so`art::CheckJNI::CallCharMethodV(_JNIEnv*, _jobject*, _jmethodID*, char*))
    CallCharMethodA = {jchar (*)(JNIEnv *, jobject, jmethodID, jvalue *) | 0xb3a67059} (libart.so`art::CheckJNI::CallCharMethodA(_JNIEnv*, _jobject*, _jmethodID*, jvalue*))
    CallShortMethod = {jshort (*)(JNIEnv *, jobject, jmethodID, ...) | 0xb3a69cf3} (libart.so`art::CheckJNI::CallShortMethod(_JNIEnv*, _jobject*, _jmethodID*, ...))
    CallShortMethodV = {jshort (*)(JNIEnv *, jobject, jmethodID, va_list) | 0xb3a69c89} (libart.so`art::CheckJNI::CallShortMethodV(_JNIEnv*, _jobject*, _jmethodID*, char*))
    CallShortMethodA = {jshort (*)(JNIEnv *, jobject, jmethodID, jvalue *) | 0xb3a66fef} (libart.so`art::CheckJNI::CallShortMethodA(_JNIEnv*, _jobject*, _jmethodID*, jvalue*))
    CallIntMethod = {jint (*)(JNIEnv *, jobject, jmethodID, ...) | 0xb3a69c20} (libart.so`art::CheckJNI::CallIntMethod(_JNIEnv*, _jobject*, _jmethodID*, ...))
obj = {jobject | 0xbfcc426c} 0xbfcc426c

1 ответ

Решение

Ты звонишь returnInt() до SuperpoweredExample(), Поэтому вы разыменовываете нулевой указатель, example,

Также вы ничего не возвращали из функции, объявленной как возвращающая jint

Тебе нужно:

extern "C" JNIEXPORT jint Java_com_superpowered_crossexample_MainActivity_returnInt(JNIEnv * __unused javaEnvironment, jobject __unused obj) {
    return example->returnInt();
}
Другие вопросы по тегам