HELP: Passing and Returning Objects using JNI

Discussion in 'Java' started by Vikas, Aug 22, 2003.

  1. Vikas

    Vikas Guest

    Hi all,

    I am learning JNI and writing small examples to understand the
    concepts better. I am having trouble with the following programs and
    would appreciate it if someone could help me out. I am also sending
    the code and output..

    Thanks,
    Vikas


    ************************* OBJECTIVE OF THIS PROGRAM
    *************************

    I am creating 2 objects of type Employee {String name, int salary} ..
    My aim is to pass these 2 objects to my native program (written in C)
    ... I then concatenate the 2 employee names and add their salaries ...
    After doing this I have to create a new object of type Employee on the
    C side .. Fill that object with the concatenated name, sum of salaries
    .... Return that object back to the Java prg. which prints out the
    member variables ....


    ************************* OUTPUT *************************
    D:\JavaWork\JNI>java jniClasses.ReceivingObject
    JAVA PASS 1
    JAVA PASS 2
    JAVA PASS 3
    fid1 = 34
    fid2 = 50
    fid3 = 34
    fid4 = 50
    C PASS 1
    stringUTFLength =24
    *** C SIDE *** Combined NAMES = Larry Ellison Bill Gates
    *** C SIDE *** Combined SALARY = 40000
    C PASS 2
    Sizeof objClass = 4
    constructorMethodID = 9890712
    Sizeof returnObj = 4
    fid5 = 34
    NULL RETURNED TO fid6
    fid6 = 0
    C PASS 3
    C PASS 4
    Exception in thread "main" java.lang.NoSuchFieldError: salary
    at jniClasses.ReceivingObject.addEmployees(Native Method)
    at jniClasses.ReceivingObject.main(ReceivingObject.java:22)



    ************************* JAVA CODE *************************

    // START OF JAVA PROGRAM


    package jniClasses;

    import java.io.*;
    import java.util.*;

    class ReceivingObject {


    public native Employee addEmployees(Employee s1, Employee s2); //
    declaration here

    public static void main(String args[]) {


    System.out.println("JAVA PASS 1");
    Employee e1 = new Employee("Larry Ellison ", 15000);
    Employee e2 = new Employee("Bill Gates", 25000);

    System.out.println("JAVA PASS 2");
    ReceivingObject ro = new ReceivingObject();
    System.out.println("JAVA PASS 3");

    Employee e3 = ro.addEmployees(e1, e2);

    System.out.println("JAVA ====== Object class "+e3.getClass());


    System.out.println("JAVA PASS 4");

    System.out.println("New Employee Details");
    System.out.println("Empoyee Name = " + e3.name);

    System.out.println("Empoyee Salary = " + e3.salary);

    System.out.println("JAVA PASS 5");

    }



    static {

    System.loadLibrary("ReceiveObject");

    }


    }


    class Employee{

    public String name;
    public int salary;


    public Employee(String tempName, int tempSalary) { // constructor

    this.name = tempName;
    this.salary = tempSalary;

    }



    }

    // END OF JAVA PROGRAM



    ************************* C CODE *************************

    // START OF C PROGRAM

    #include "jniClasses_ReceivingObject.h"
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>


    /*
    * Class: jniClasses_ReceivingObject
    * Method: addEmployees
    * Signature: (LjniClasses/Employee;LjniClasses/Employee;)LjniClasses/Employee;
    */
    JNIEXPORT jstring JNICALL Java_jniClasses_ReceivingObject_addEmployees
    (JNIEnv *env, jobject defaultObj, jobject emp1, jobject emp2) {


    jfieldID fid1, fid2, fid3, fid4, fid5, fid6;
    jstring firstEmployeeNameJava, secondEmployeeNameJava, myTempName;
    jmethodID constructorMethodID;
    jsize stringUTFLength;

    jobject combinedEmployeeNameJava; // Java style strings

    jint firstEmployeeSalary, secondEmployeeSalary, combinedSalary,
    myTempSalary; // Java style integers
    jclass objClass;
    jobject returnObj; // object to be returned

    const char *firstEmployeeNameC, *secondEmployeeNameC; // C style
    Names
    char *combinedEmployeeNameC;

    jclass class1 = (*env)->GetObjectClass(env, emp1);
    jclass class2 = (*env)->GetObjectClass(env, emp2);

    fid1 = (*env)->GetFieldID(env, class1, "name",
    "Ljava/lang/String;"); // Get Name
    if (fid1 == 0) printf("NULL RETURNED TO fid1\n");
    printf("fid1 = %d\n",fid1);

    fid2 = (*env)->GetFieldID(env, class1, "salary","I"); // Get
    Salary
    if (fid2 == 0) printf("NULL RETURNED TO fid2\n");
    printf("fid2 = %d\n",fid2);

    fid3 = (*env)->GetFieldID(env, class2, "name", "Ljava/lang/String;");
    if (fid3 == 0) printf("NULL RETURNED TO fid3\n");
    printf("fid3 = %d\n",fid3);

    fid4 = (*env)->GetFieldID(env, class2, "salary","I");
    if (fid4 == 0) printf("NULL RETURNED TO fid4\n");
    printf("fid4 = %d\n",fid4);

    firstEmployeeNameJava = (*env)->GetObjectField(env, emp1, fid1); //
    java type String
    firstEmployeeNameC = (*env)->GetStringUTFChars(env,
    firstEmployeeNameJava, NULL);
    firstEmployeeSalary = (*env)->GetIntField(env, emp1, fid2);


    secondEmployeeNameJava = (*env)->GetObjectField(env, emp2, fid3); //
    java type String
    secondEmployeeNameC = (*env)->GetStringUTFChars(env,
    secondEmployeeNameJava, NULL);
    secondEmployeeSalary = (*env)->GetIntField(env, emp2, fid4);

    // Combined Employee's Name
    combinedEmployeeNameC = (char*) malloc( strlen(firstEmployeeNameC) +
    strlen(secondEmployeeNameC) + 1 ); //+ 1 for '\0'

    printf("C PASS 1\n");
    strcpy(combinedEmployeeNameC, "");
    strcpy(combinedEmployeeNameC, firstEmployeeNameC);
    strcat(combinedEmployeeNameC, secondEmployeeNameC); // perform the
    string concatenation in C

    combinedEmployeeNameJava = (*env)->NewStringUTF( env,
    combinedEmployeeNameC ); // Construct a Java Style String Name
    stringUTFLength = (*env)->GetStringUTFLength(env,
    combinedEmployeeNameJava);
    printf("stringUTFLength =%d\n", stringUTFLength);

    combinedSalary = firstEmployeeSalary + secondEmployeeSalary; //
    Combined Employee's Salary

    printf("*** C SIDE *** Combined NAMES = %s\n",
    combinedEmployeeNameC);
    printf("*** C SIDE *** Combined SALARY = %d\n", combinedSalary);


    // Now construct the new object and return that

    printf("C PASS 2\n");


    // Load the ReceivingObject class
    objClass = (*env)->FindClass(env,"jniClasses/ReceivingObject"); //
    FindClass()
    if (objClass == 0) printf("NULL RETURNED in FindClass()\n");
    printf("Sizeof objClass = %d\n", sizeof(objClass) );

    /*************************************************************************
    // Allocates a new Java object without invoking any of the
    constructors
    returnObj = (*env)->AllocObject(env, objClass);
    if (returnObj == 0) printf("NULL RETURNED in AllocObject()\n");
    printf("Sizeof returnObj = %d\n", sizeof(returnObj) );
    **************************************************************************/


    // Get the methodID for the constructor first
    constructorMethodID = (*env)->GetMethodID(env, objClass,
    "<init>","()V");

    if (constructorMethodID == 0) printf("NULL RETURNED TO
    constructorMethodID\n");
    printf("constructorMethodID = %d\n",constructorMethodID);

    // Create the object
    returnObj = (*env)->NewObject(env, class1, constructorMethodID,
    myTempName, myTempSalary);
    printf("Sizeof returnObj = %d\n", sizeof(returnObj) );


    fid5 = (*env)->GetFieldID (env, class1, "name",
    "Ljava/lang/String;"); // combined name
    if (fid5 == 0) printf("NULL RETURNED TO fid5\n");
    printf("fid5 = %d\n",fid5);


    fid6 = (*env)->GetFieldID (env, objClass, "salary", "I"); //
    combined salaries
    if (fid6 == 0) printf("NULL RETURNED TO fid6\n");
    printf("fid6 = %d\n",fid6);


    printf("C PASS 3\n");


    // Filling the values to the object
    (*env)->SetObjectField (env, returnObj, fid5,
    combinedEmployeeNameJava);
    (*env)->SetIntField (env, returnObj, fid6, combinedSalary);


    printf("C PASS 4\n");


    return returnObj;


    }

    // END OF C PROGRAM
     
    Vikas, Aug 22, 2003
    #1
    1. Advertising

  2. On 22 Aug 2003 06:45:46 -0700, Vikas wrote:
    > I am learning JNI and writing small examples to understand the
    > concepts better. I am having trouble with the following programs and
    > would appreciate it if someone could help me out. I am also sending
    > the code and output..


    Your code fails where you try to find the "salary" field in the
    ReceivingObject class, but there is no such field. Just prior to that
    you successfully looked up the "name" field in the Employee class, so
    there is some inconsistency here.

    Either pass the right class variable, probably "class1" (not
    "objClass"), or make sure that ReceivingObject has the appropriate
    fields.

    According to the signature of the native method, combining two
    employees should create a new employee, so I suspect the real error is
    that you created a new ReceivingObject to contain the values.

    A few tips:

    - when your method receives two objects of the same class (e.g.
    Employee), you don't need to call GetObjectClass() separately for
    each of them, or look up their field and method ids separately. You
    can use the same class and field ids when you create the return object
    later as well.

    - when you create objects from JNI, it is generally much easier to
    pass initial values via the constructor, rather then look up fields
    and set the values individually.

    - when a JNI function fails, try calling something like this to find
    out why:

    if ((*env)->ExceptionOccurred(env)) {
    ((*env)->ExceptionDescribe(env));
    }

    /gordon

    --
    [ do not send me private copies of your followups ]
    g o r d o n . b e a t o n @ e r i c s s o n . c o m
     
    Gordon Beaton, Aug 22, 2003
    #2
    1. Advertising

  3. Vikas

    Vikas Guest

    Thanks for the tips, gordon .. they were really helpful ... I also
    managed to solve the problem I had

    Thanks/Vikas

    Gordon Beaton <> wrote in message news:<3f4635a5$>...
    > On 22 Aug 2003 06:45:46 -0700, Vikas wrote:
    > > I am learning JNI and writing small examples to understand the
    > > concepts better. I am having trouble with the following programs and
    > > would appreciate it if someone could help me out. I am also sending
    > > the code and output..

    >
    > Your code fails where you try to find the "salary" field in the
    > ReceivingObject class, but there is no such field. Just prior to that
    > you successfully looked up the "name" field in the Employee class, so
    > there is some inconsistency here.
    >
    > Either pass the right class variable, probably "class1" (not
    > "objClass"), or make sure that ReceivingObject has the appropriate
    > fields.
    >
    > According to the signature of the native method, combining two
    > employees should create a new employee, so I suspect the real error is
    > that you created a new ReceivingObject to contain the values.
    >
    > A few tips:
    >
    > - when your method receives two objects of the same class (e.g.
    > Employee), you don't need to call GetObjectClass() separately for
    > each of them, or look up their field and method ids separately. You
    > can use the same class and field ids when you create the return object
    > later as well.
    >
    > - when you create objects from JNI, it is generally much easier to
    > pass initial values via the constructor, rather then look up fields
    > and set the values individually.
    >
    > - when a JNI function fails, try calling something like this to find
    > out why:
    >
    > if ((*env)->ExceptionOccurred(env)) {
    > ((*env)->ExceptionDescribe(env));
    > }
    >
    > /gordon
     
    Vikas, Aug 27, 2003
    #3
    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. Alex
    Replies:
    1
    Views:
    2,330
    Gordon Beaton
    Nov 30, 2004
  2. Replies:
    25
    Views:
    30,011
  3. Victor Bazarov
    Replies:
    25
    Views:
    914
    E. Robert Tisdale
    Mar 23, 2005
  4. bernd
    Replies:
    1
    Views:
    799
    bernd
    Jun 13, 2008
  5. adityar7
    Replies:
    23
    Views:
    4,588
    Aditya Rajgarhia
    Jul 17, 2008
Loading...

Share This Page