18

I need to implement callback function in Java using “interface”. I have wrote the application part as MyJavaFunction(int size, m_GetSizeInterface);

m_GetSizeInterface is an Interface which contains the callback function GetSize. This GetSize method is override in the application. In JNI I need to call a CPP function having prototype int MyCPPFunction(int size, int (*callback)(int* ID));

How can I pass this GetSize as parameter to MyCPPFunction in JNI? Please help

public int GetSize (m_SizeClass arg0)
{
    g_size = arg0.size;
        return 0;
}
0

2 Answers 2

19

The complication here is that you want to invoke native C++ code which you, in turn, want to invoke a java method. This is actually a bit tricky.

You need to create a JNI C++ function for java to call, and a C++ function matching the MyCPPFunction callback signature. The latter will act as a wrapper to call the java method.

Because the wrapper will need information about the JNI environment, which cannot be provided by parameters (lest we ruin the signature) you create a few global variables to hold it:

jobject g_getSizeIface;
jmethodID g_method;
JNIEnv *g_env;

The C++ function which java will call is the following:

JNIEXPORT void JNICALL Java_ClassName_MyCPPFunction
     (JNIEnv *env, jint size, jobject getSizeInterface)
{
      jclass objclass = env->GetObjectClass(getSizeInterface);
      jmethodID method = env->GetMethodID(objclass, "GetSize", "(m_SizeClass)I");
      if(methodID == 0){
          std::cout << "could not get method id!" << std::endl;
          return;
      }
      g_method = method;
      g_getSizeIface = getSizeInterface;
      g_env = env
      MyCPPFunction(size, WrapperFunc);
}

And the wrapper function is thus:

int WrapperFunc(int *id)
{
      jint retval;
      //marshalling an int* to a m_SizeClass boogy-woogy.
      ...
      g_env->ExceptionClear();
      retval = g_env->CallIntMethod(g_getSizeIface, g_method, 
                                    /*marshalled m_SizeClass*/);
      if(g_env->ExceptionOccurred()){
          //panic! Light fires! The British are coming!!!
          ...
          g_env->ExceptionClear();
      }     
      return rvalue;
}
Sign up to request clarification or add additional context in comments.

3 Comments

can we have full functional sample code..what will be declaration at Java layer?
what if one needs to register the callback with native code multiple times (passing different interface implementations), so that each WrapperFunc registration has an associated interface object/method to invoke
How do you call the Java_ClassName_MyCPPFunction function from your java code?
0
#include <functional>
#include <cstdlib>
#include <map>

class SimpleQueueEvent {

public:

    SimpleQueueEvent(){};
    ~SimpleQueueEvent(){};

    //for C++ code call
    int queueEvent(std::function<void(void)> func){
        int curTime = time(0) + rand() % 10000;
        eventMaps.insert(std::map<int, std::function<void(void)>>::value_type(curTime, func));
        return curTime;

        //Call Java method to invoke method, such as
        //env->FindClass("....");
        //jmethodID method = env->FindMethod("onPostQueueEvent"...);
        //env->InvokeVoidMethod();

        //Java code like this..
        // private void onPostQueueEvent(final int eventId){
        // listener.PostQueueEvent(new Runnable() {
        //    public void run() {
        //        nativeEventFunc(eventId);
        //    }
        // });
        // private static native void nativeEventFunc(int eventId);

    }

    void nativeEventFunc(int eventId){
        if(eventMaps.find(eventId) != eventMaps.end()){
            std::function<void(void)> func = eventMaps.at(eventId);
            func();
        }
    }



private:
    std::map<int, std::function<void(void)>> eventMaps;


};

//and test code is:

 SimpleQueueEvent queueEvent;
    std::function<void(void)> func = [](){
        printf("native runnable..\n");
    };

    int evenId = queueEvent.queueEvent(func);
    queueEvent.nativeEventFunc(evenId);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.