Search code examples
javaandroidandroid-ndkjava-native-interface

How to pass a C++ function pointer into a library's JNI functions


I am developing an audio library (AAR) which helps to process some signal processing apps. In my library, I will have a general signal processing block (written in C++ and layered by JNI). After my processing, my library needs to call some "callback" functions (defined by the library users), so the users can make their "customized" responses to the processed signals.

I hope this is interfaced in C++ so this user-defined "callback" function can also be used in my iOS library. But I am not sure how to do it.

Following is a example of my problem

---------- here is my AAR library --------------

in jni.c

void (*userCallback)(int []);
void onAudioRecorded(int[] audio) { // this function is called by Java
    // So some library processing
    int[] processedAudio = libraryProcessing(audio);
    // Pass this processed audio to the user-defined function
    userCallback(audio);
}

---------- here is in some user's projects include my AAR library --------------

in users app's user_jni.c

void setLibraryCallback() {
    // HERE IS MY PROBLEM
    // HOW CAN I SET MY LIBRARY’s userCallback to onAudioProcessed
}

void onAudioProcessed(int[] processedAudio) {
    // Do some further processing
    int[] finalAudio = userDefinedProcessing(processedAudio);
    // Make some reactions based on finalAudio
}

Solution

  • You need another layer of indirection. Since there's no such things as a function pointer in Java, you can't pass one to JNI. Instead, you have to pass it a Java object. Make an interface

    public interface Callback {
       void onAudioRecorded(int data[]);
    }
    

    Pass an instance of that to JNI. Then in JNI, write a function that calls the onAudioRecorded method of that Java object, and pass it to the function that needs a callback. remember that you need to hold an instance of that object at the JNI layer, and free it when you're finally done with it.