V
Vikas
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/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
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/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