Superpowered Android JNI: understanding "JNI(jintArray ..." format

381 views Asked by At

The Superpowered "Simple USB Example" uses the code below to update the UI on the Java side based on a C++ method. This is the first time I've seen JNI alone followed by a method. I've seen JNIEXPORT in similar situations, but not just JNI. I'd like to learn more about this usage but haven't had any luck trying to Google it. Any explanations or references would be appreciated!

C++ Code:

// This is called by the MainActivity Java object periodically.
JNI(jintArray, getLatestMidiMessage, PID)(JNIEnv *env, jobject __unused obj) {
    jintArray ints = env->NewIntArray(4);
    jint *i = env->GetIntArrayElements(ints, NULL);
    pthread_mutex_lock(&mutex);
    i[0] = latestMidiCommand;
    i[1] = latestMidiChannel;
    i[2] = latestMidiNumber;
    i[3] = latestMidiValue;
    pthread_mutex_unlock(&mutex);
    env->ReleaseIntArrayElements(ints, i, NULL);
    return ints;
}

Java code:

 // Update UI every 40 ms.
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                int[] midi = getLatestMidiMessage();
                switch (midi[0]) {
                    case 8: textView.setText(String.format(Locale.ENGLISH, "Note Off, CH %d, %d, %d", midi[1] + 1, midi[2], midi[3])); break;
                    case 9: textView.setText(String.format(Locale.ENGLISH, "Note On, CH %d, %d, %d", midi[1] + 1, midi[2], midi[3])); break;
                    case 11: textView.setText(String.format(Locale.ENGLISH, "Control Change, CH %d, %d, %d", midi[1] + 1, midi[2], midi[3])); break;
                }
                handler.postDelayed(this, 40);
            }
        };
        handler = new Handler();
        handler.postDelayed(runnable, 40);
    }
1

There are 1 answers

1
Gabe Sechan On BEST ANSWER

Look at the code in that example:

// Beautifying the ugly Java-C++ bridge (JNI) with these macros.
#define PID com_superpowered_simpleusb_SuperpoweredUSBAudio // Java package name and class name. Don't forget to update when you copy this code.
#define MAKE_JNI_FUNCTION(r, n, p) extern "C" JNIEXPORT r JNICALL Java_ ## p ## _ ## n
#define JNI(r, n, p) MAKE_JNI_FUNCTION(r, n, p)

He's using some macro magic to make things "cleaner". In reality it makes it less wordy but far harder to understand, and production code should never have stuff like this.