java — сверхспособный Android NDK: возвращение int преуспевает в & quot; extern & quot; блок, не в вызываемой функции

Я пытаюсь выяснить, как вернуть 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();
}
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]