CallBack JNI help

Discussion in 'Java' started by Homer, Nov 15, 2005.

  1. Homer

    Homer Guest

    Can somebody help me please how I can call my callback function in C++:

    Java:


    class DirectoryWatcher {
    public native void watchDirectory();
    public native void callBack(String status);


    static {
    System.loadLibrary("watcher");
    }


    public void callback(String status) {
    System.out.println("Honey, I am home...");
    }


    public static void main(String[] args) {
    DirectoryWatcher dw = new DirectoryWatcher();
    dw.watchDirectory();
    }



    }


    C++:

    __gc class Watcher
    {
    public:
    void Go(String * s){
    .......................
    callJavaCallBack();
    }


    void callJavaCallBack() {
    HERE IS THE MISSING PART (WHAT SHOULD I DO HERE? Where
    should I get env, obj)
    }



    };


    JNIEXPORT void JNICALL
    Java_DirectoryWatcher_callbback(JNIEnv *env, jobject obj, jint depth)
    {
    (*env)->CallVoidMethod(env, obj,
    instanceMethodCall_callback);
    }


    JNIEXPORT void JNICALL
    Java_DirectoryWatcher_watchDirectory(JNIEnv *env, jobject obj)
    {
    instanceMethodCall_callback = (*env)->GetMethodID(env, cls,
    "callback", "()V");

    Watcher * w=new Watcher();
    w->Go("c:\\test");
    return;
    }
    Homer, Nov 15, 2005
    #1
    1. Advertising

  2. On 15 Nov 2005 06:13:51 -0800, Homer wrote:
    > Can somebody help me please how I can call my callback function in C++:


    [...]

    > void callJavaCallBack() {
    > HERE IS THE MISSING PART (WHAT SHOULD I DO HERE? Where
    > should I get env, obj)
    > }


    If your callback is an instance method, then your setup code should
    normally provide an appropriate object for you to use and store a
    global reference to it so that it is visible from the place where you
    invoke the callback.

    In order to get a valid JNIEnv*, the thread invoking the callback
    function must attach to the JVM using methods described in the
    invocation API (GetCreatedJavaVMs() and AttachCurrentThread(), for
    example).

    At that point you can lookup the method ID in the target object's
    class (e.g. with FindObjectClass() and GetMethodId()), and then use
    CallVoidMethod() or similar to make the actual call.

    If your callback function needs additional objects as arguments, then
    you either need to create them yourself, or your setup code needs to
    provide global references to them.

    /gordon

    --
    [ do not email me copies of your followups ]
    g o r d o n + n e w s @ b a l d e r 1 3 . s e
    Gordon Beaton, Nov 15, 2005
    #2
    1. Advertising

  3. Homer

    Roedy Green Guest

    On 15 Nov 2005 06:13:51 -0800, "Homer" <> wrote,
    quoted or indirectly quoted someone who said :

    >Can somebody help me please how I can call my callback function in C++:


    To see how to set up the Java side of things, see
    http://mindprod.com/jgloss/callback.html
    --
    Canadian Mind Products, Roedy Green.
    http://mindprod.com Java custom programming, consulting and coaching.
    Roedy Green, Nov 15, 2005
    #3
  4. On 16 Nov 2005 07:04:19 -0800, Homer wrote:
    > But I am still getting "Unhandled Exception: StackOverflowException."


    First, what is that declaration of "struct _jmethodID" doing there?

    Your calls to GetMethodID() and CallStaticVoidMethod() do not agree
    with each other - either the method is static or it isn't. Use
    GetStaticMethodID() or CallVoidMethod().

    Finally, you should be checking that each of the calls to JNI
    functions has succeeded before you proceed with potentially NULL or
    invalid values and a raised exception in the JVM.

    /gordon

    --
    [ do not email me copies of your followups ]
    g o r d o n + n e w s @ b a l d e r 1 3 . s e
    Gordon Beaton, Nov 16, 2005
    #4
  5. On 16 Nov 2005 07:09:42 -0800, Homer wrote:
    > BTW. I am using this command to complie (VC++):
    >
    > cl -Ic:\java\include -Ic:\java\include\win32 -LD hand.cpp
    > -Fewatcher.dll /clr
    >
    > If I remove /clr I am getting following error:
    >
    > hand.cpp(7) : fatal error C1190: managed targeted code requires '#using
    ><mscorlib.dll>' and '/clr' option
    >
    >
    > And also I added "struct _jmethodID {};" because I was getting this
    > error:
    >
    > Unhandled Exception: System.TypeLoadException: Could not load type
    > _jmethodID from assembly watcher


    I haven't got a clue how to compile DLLs on Windows, but I'll guess
    that maybe one of the following is true:

    - you haven't included the proper header files from your JDK
    - you haven't included the header that javah generated
    - you didn't specify the fully qualified classname when you used javah
    - you haven't followed *exactly* the names and signatures in the generated header

    Someone else might have comments about the compiler command.

    /gordon

    --
    [ do not email me copies of your followups ]
    g o r d o n + n e w s @ b a l d e r 1 3 . s e
    Gordon Beaton, Nov 16, 2005
    #5
  6. Homer

    Homer Guest

    Thanks Gordon for your help. Following your instruction here is what
    I've done:

    JNIEnv *m_env;
    JavaVM *m_vm;
    struct _jmethodID {};

    JNIEXPORT void JNICALL
    Java_DirectoryWatcher_watchDirectory(JNIEnv *env, jobject obj)
    {
    env->GetJavaVM( &m_vm );
    Watcher * w=new Watcher();
    w->Go("c:\\test");
    return;
    }


    void doCallback(){
    m_vm->AttachCurrentThread( (void**) &m_env, NULL );
    jclass cls = m_env->FindClass( "DirectoryWatcher" );
    jmethodID mid = m_env->GetMethodID(cls, "callback", "(I)V");
    m_env->CallStaticVoidMethod(cls, mid);
    }

    But I am still getting "Unhandled Exception: StackOverflowException."

    Any idea?


    Thanks in advance,

    Homer
    Homer, Nov 16, 2005
    #6
  7. Homer

    Homer Guest

    BTW. I am using this command to complie (VC++):

    cl -Ic:\java\include -Ic:\java\include\win32 -LD hand.cpp
    -Fewatcher.dll /clr

    If I remove /clr I am getting following error:

    hand.cpp(7) : fatal error C1190: managed targeted code requires '#using
    <mscorlib.dll>' and '/clr' option


    And also I added "struct _jmethodID {};" because I was getting this
    error:

    Unhandled Exception: System.TypeLoadException: Could not load type
    _jmethodID from assembly watcher
    Homer, Nov 16, 2005
    #7
  8. Homer

    Roedy Green Guest

    On 16 Nov 2005 16:24:32 +0200, Gordon Beaton <> wrote,
    quoted or indirectly quoted someone who said :

    >I haven't got a clue how to compile DLLs on Windows, but I'll guess
    >that maybe one of the following is true:


    see http://mindprod.com/jgloss/jni.html
    for help on setting up your compiler.
    --
    Canadian Mind Products, Roedy Green.
    http://mindprod.com Java custom programming, consulting and coaching.
    Roedy Green, Nov 16, 2005
    #8
  9. Homer

    Homer Guest

    Thanks Gordon for your quick response. I search on the NET and
    everybody was saying add "struct _jmethodID {}; " to your code to not
    get TypeLoadException. I have no idea what does it mean.

    I added some error printing to my code and I see that methodID I am
    getting is zero:

    void doCallback(int i){
    printf("1111\n");
    m_vm->AttachCurrentThread( (void**) &m_env, NULL );
    printf("2222\n");
    jclass cls = m_env->FindClass( "DirectoryWatcher" );
    printf("3333\n");
    jmethodID mid = m_env->GetMethodID(cls, "callback", "(I)V");
    if(cls == NULL){ printf("error"); return; }
    if(mid == 0){printf("mid is Zero"); return; }
    printf("4444\n");
    m_env->CallVoidMethod(cls, mid);
    printf("5555\n");
    }

    The result is:
    1111
    2222
    3333
    mid is Zero


    I can email to the code if you want.


    Thanks,

    Homer
    Homer, Nov 16, 2005
    #9
  10. On 16 Nov 2005 10:28:26 -0800, Homer wrote:
    > Thanks Gordon for your quick response. I search on the NET and
    > everybody was saying add "struct _jmethodID {}; " to your code to not
    > get TypeLoadException. I have no idea what does it mean.


    It seems to me that if you need to do something like that to get a
    clean compile, then your JDK is broken or incomplete.

    > I added some error printing to my code and I see that methodID I am
    > getting is zero:
    >
    > void doCallback(int i){
    > printf("1111\n");
    > m_vm->AttachCurrentThread( (void**) &m_env, NULL );
    > printf("2222\n");
    > jclass cls = m_env->FindClass( "DirectoryWatcher" );
    > printf("3333\n");
    > jmethodID mid = m_env->GetMethodID(cls, "callback", "(I)V");
    > if(cls == NULL){ printf("error"); return; }
    > if(mid == 0){printf("mid is Zero"); return; }
    > printf("4444\n");
    > m_env->CallVoidMethod(cls, mid);
    > printf("5555\n");
    > }
    >
    > The result is:
    > 1111
    > 2222
    > 3333
    > mid is Zero
    >
    > I can email to the code if you want.


    Please don't.

    Did FindClass() succeed? (is cls non-NULL?) Does DirectoryWatcher
    belong to a package?

    If GetMethodID returns zero, it means that the name or the signature
    is wrong, that you're looking in the wrong class, or that you aren't
    using the right function to look it up. Note that you must use
    GetStaticMethodID() to find a static method, and GetMethodID() to find
    a non-static method.

    To call a non-static method, you need to pass an object (not its
    class) to CallVoidMethod(). If the method is in fact static, use
    CallStaticVoidMethod() and pass the class as you've done here.

    Use javap -s <classname> to see a list of symbol names and signatures
    actually found in the class.

    /gordon

    --
    [ do not email me copies of your followups ]
    g o r d o n + n e w s @ b a l d e r 1 3 . s e
    Gordon Beaton, Nov 16, 2005
    #10
  11. Homer

    Homer Guest

    Thanks so much for your help. It's working now. The trick was to change
    everything to Static. (I guess I was not passeing an object after all).
    Homer, Nov 16, 2005
    #11
  12. On 16 Nov 2005 10:28:26 -0800, Homer wrote:
    > I search on the NET and everybody was saying add "struct _jmethodID
    > {}; " to your code to not get TypeLoadException. I have no idea what
    > does it mean.


    Apparently a bug in dot-NET. More information and a workaround here:

    http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6220093

    /gordon

    --
    [ do not email me copies of your followups ]
    g o r d o n + n e w s @ b a l d e r 1 3 . s e
    Gordon Beaton, Nov 17, 2005
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mic

    JNI callback and jar

    Mic, Feb 12, 2004, in forum: Java
    Replies:
    1
    Views:
    495
    Gordon Beaton
    Feb 13, 2004
  2. Storm
    Replies:
    2
    Views:
    890
    Storm
    Oct 16, 2004
  3. John Smith
    Replies:
    5
    Views:
    6,741
    Chris Uppal
    Jul 27, 2005
  4. Homer

    JNI & CallBack: Please help

    Homer, Oct 31, 2005, in forum: Java
    Replies:
    8
    Views:
    763
    Homer
    Nov 2, 2005
  5. Replies:
    1
    Views:
    3,311
    Chris Uppal
    Feb 24, 2006
Loading...

Share This Page