CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 3 of 3
  1. #1
    Join Date
    Apr 1999
    Location
    Toulouse, France
    Posts
    8

    JNI : Out parameters, simulating pointers

    Hello,
    I'm trying to link some C function with this prototype :
    HANDLE myFunc([IN] HWND, [IN] unsigned char *, [OUT] WORD *, [OUT] WORD *, [OUT] unsigned char *)
    Don't bother too much about HANDLE, HWND, WORD etc they're just pointer values, longs etc. My actual problem is that my function returns many values (a HANDLE, two
    WORDs and an unsigned char -- actually it's a string).

    To manage to map pointers on Words, I built up a class Word, with a single parameter value (an int).
    In C code (JNI), I therefore need to modify the Word object and set its value. I've read this is possible with SetIntField method and so on.
    ... but in my case, I can't get it to work (and I can't see my error) : object doesn't seem to be modified... Maybe I haven't got the right fieldID, or the right class, I don't understand...

    Here's my code, it isn't long. If someone can help me out...
    PS. I've been through the JNI section, in Codeguru, and found an interesting Java Tip of Geoff Friesen, but I seem to be doing it correctly, so I don't understand.

    in Word.java

    class Word {
    public int value;
    Word(){}
    Word(int i){ value = i; }

    }
    in GDAPI.java
    class GDAPI {
    static {
    // link to my DLL
    System.loadLibrary("gdirect");
    }

    public native long open(long hWnd,
    String szTitle,
    Word pIsOk,
    Word pIsInit,
    String szName //out
    );

    public static void main(String args[]){
    String name = "toto";
    Word ok = new Word(0);
    Word init = new Word(0);
    GDAPI api= new GDAPI();

    System.out.println("In JAVA, before call to open");

    long h = api.open(0,"Coucou",ok,init,name);

    System.out.println("In Java after call :");
    System.out.println("\tok="+ok.value);
    System.out.println("\tinit="+init.value);
    System.out.println("\tname="+name);
    System.out.println("\th="+h);
    [...]
    }
    }



    In C :
    JNIEXPORT jlong JNICALL
    Java_GDAPI_open(JNIEnv *env,
    jobject obj_this,
    jlong hwnd, // in
    jstring jstrTitle, // in (not out !)
    jobject joIsOk, // only out
    jobject joIsInit, // only out
    jstring jstrName){ // only out
    char *sztitle;
    char szname[128];
    WORD w_ok,w_init;
    HANDLE h;
    jclass cls_ok, cls_init;
    jfieldID fid_ok,fid_init;

    printf("> Java_GDAPI_open\n");

    // initialisations
    obj_this = obj_this;
    h = NULL;
    w_ok = 0;
    w_init = 0;
    sztitle = (char *)(*env)->GetStringUTFChars(env,jstrTitle,0);

    // call to real C Function
    printf("CFunction(hwnd=%08lx,title=%s,&w_ok=%08lx, &w_init=%08lx,szname=%s)\n",hwnd,sztitle,&w_ok,&w_init,szname);

    h = CFunction((HWND) hwnd, (unsigned char*)sztitle, &w_ok, &w_init, (unsigned char*)szname);

    printf("returns h=%08lx w_ok=%d w_init=%d szname=%s\n",h,w_ok,w_init,szname);

    // updating IsOk object
    printf("updating isOk\n");
    cls_ok = (*env)->GetObjectClass(env,joIsOk);
    fid_ok = (*env)->GetFieldID(env,cls_ok,"value","I");
    if (fid_ok == 0) return 0;
    (*env)->SetIntField(env,cls_ok,fid_ok, (jint) w_ok);

    // updating IsInit
    printf("updating IsInit\n");
    cls_init = (*env)->GetObjectClass(env,joIsInit);
    fid_init = (*env)->GetFieldID(env,cls_init,"value","I");
    if (fid_init == 0) return 0;
    (*env)->SetIntField(env,cls_init,fid_init, (jint) w_init);

    // updating string object
    printf("updating string \n");
    jstrName = (*env)->NewStringUTF(env,szname);

    // free
    printf("freeing \n");
    (*env)->ReleaseStringUTFChars(env, jstrTitle, sztitle);

    printf("< Java_GDAPI_open\n");
    return (jlong) h;
    }




    --
    Axelle Apvrille - MSI

  2. #2
    Join Date
    Apr 1999
    Location
    Toulouse, France
    Posts
    8

    Re: JNI : Out parameters, simulating pointers

    Hello,
    Don't worry any longer about my post, I found the error in my code : when you call SetIntField, second parameter is object and not class, whereas when you call SetStaticIntField it's the class.
    It seems quite logical, but I hadn't seen my error.
    Sorry for those who had a look at that code.

    Axelle Apvrille - MSI

  3. #3
    Join Date
    Oct 1999
    Location
    Tewskbury, MA, USA
    Posts
    2

    Re: JNI : Out parameters, simulating pointers

    I usually do about the same thing, but with the java "wrapper" classes (java.lang.Long, Integer, Float, etc.) instead of doing my own. The procedure for calling it is about the same -- I have to get a jmethodID for the "<init>" method (i.e., the constructor) with signature"(J)V" (for example -- long)

    Also, now that I look at it, it seems you could use a short (16-bits) for a WORD, and an int (32-bits) for a DWORD. Somehow I've gotten in the habit of using a java 64-bit long for a DWORD, so I suppose if I'm not wasting great quantities of memory it doesn't matter.

    I bought Essential JNI by Rob Gordon, and it seems to have useful "JNI Rules to Remember" that include your particular class/object gotcha, as well as other gotchas that I've hit (e.g., the semicolon after a class name). Those alone, plus a real documentation of the JNI API, make it worth the purchase price.


Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured