Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > HELP: Passing and Returning Objects using JNI

Reply
Thread Tools

HELP: Passing and Returning Objects using JNI

 
 
Vikas
Guest
Posts: n/a
 
      08-22-2003
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.ja va: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/EmployeeLjniClasses/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
 
Reply With Quote
 
 
 
 
Gordon Beaton
Guest
Posts: n/a
 
      08-22-2003
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
 
Reply With Quote
 
 
 
 
Vikas
Guest
Posts: n/a
 
      08-27-2003
Thanks for the tips, gordon .. they were really helpful ... I also
managed to solve the problem I had

Thanks/Vikas

Gordon Beaton <(E-Mail Removed)> wrote in message news:<3f4635a5$(E-Mail Removed)>...
> 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

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
JNI - Passing and returning complex values adityar7 Java 23 07-17-2008 12:12 AM
JNI: passing Objects containing non-primitive types back and forth bernd Java 1 06-13-2008 08:31 PM
Passing by const & and returning a temp vs passing by value and returningit Victor Bazarov C++ 25 03-23-2005 04:24 PM
JNI: Passing array of objects from C++ to Java Alex Java 1 11-30-2004 08:16 AM
IBM's JNI fails where Sun's JNI works Alex Hunsley Java 4 11-04-2003 10:34 AM



Advertisments