超级强大的 NDK Android:返回 int 在 "extern" 块中成功,在调用的函数中失败

Superpowered NDK Android: returning int succeeds in "extern" block, fails in called function

我正在尝试弄清楚如何从 C++ 函数 return 一个 int 到 Java。

在Java这边,我在一个按钮中有以下内容。我把它放在一个按钮中以确保在尝试执行 returnInt().

之前应用程序已完全加载
int testInt;
testInt = returnInt();
Log.i(TAG, "testInt");
Log.i(TAG, String.valueOf(testInt));

private native int returnInt();

在 C++ 方面,在 extern 块中 returning 一个 int 成功:

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 吗?

我正在使用 Superpowered 提供的 CrossExample 项目的克隆进行测试。 (我只是使用 CrossExample 作为一种简单的方法来玩一个功能强大的项目。)

我的项目在这里:

https://github.com/mhurwicz/myCrossExample

对 return 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

您在 SuperpoweredExample() 之前调用了 returnInt()。因此,您正在取消引用 NULL 指针,example.

此外,您没有 return 声明为 returning jint

的函数中的任何内容

你需要:

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