wood burning stoves 2.0*
The moose likes Other JSE/JEE APIs and the fly likes Return a Structure Object from C to Java Through JNI Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


JavaRanch » Java Forums » Java » Other JSE/JEE APIs
Bookmark "Return a Structure Object from C to Java Through JNI" Watch "Return a Structure Object from C to Java Through JNI" New topic
Author

Return a Structure Object from C to Java Through JNI

Ajay Singh
Ranch Hand

Joined: Jan 04, 2008
Posts: 105
HI all

i am using the JNI to return an integer array object from a C class function to the java code.Now i want to return a structure object containing the student's record (name,age etc) to the java code.can anyone tell me what changes to be made to the following c file

#include <jni.h>
#include "Hello.h"
#include <stdio.h>

struct student
{
char *name;
int age;


}student1;

student1.name="Jack";
student1.age=23;

JNIEXPORT jobject JNICALL
Java_Hello_sayHello(JNIEnv *env, jobject obj, jintArray arr)
{
return arr;
}

My java file is as under:-

public class Hello
{
static
{
System.loadLibrary("hello");
}

public native Object sayHello(int [] arr);
public static void main(String[] args)
{
Hello p = new Hello();
int arr[] = new int[10];
for (int i = 0; i < 10; i++) {
arr[i] = i;
}
int [] len = (int[]) p.sayHello(arr);

System.out.println("sum = " + len.length); //length of the array
}
}

Any help would be appriciated
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19697
    
  20

First of all, you will need to create a class similar to the structure in Java - with a String and int field.

Now you have two options:
1) create the object in Java and pass it to the native method. This then sets the fields.
2) create the object in the native method.

Check JNI 1.1 Specification, especially JNI Functions.

Here's a little code to show how an object can be created using JNI:
<blockquote>code:
<pre name="code" class="core">jclass cls;
jmethodID constructor;
jvalue args[2];
jobject object;

// get a reference to your class if you don't have it already
cls = (*env)->FindClass(env, "mypackage/Student");
// get a reference to the constructor; the name is <init>
constructor = (*env)->GetMethodID(env, cls, "<init>", "(ILjava/lang/String;)V");
// set up the arguments; i means int, l means object
args[0].i = 23;
args[1].l = (*env)->NewStringUTF(env, "Jack");
object = (*env)->NewObjectA(env, cls, constructor, args);
</pre>
</blockquote>
<blockquote>code:
<pre name="code" class="core">package mypackage;

public class Student
{
private int age;
private String name;

public Student(int age, String name)
{
this.age = age;
this.name = name;
}

// the rest of the class
}
</pre>
</blockquote>
[ July 17, 2008: Message edited by: Rob Prime ]

SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6
How To Ask Questions How To Answer Questions
Ajay Singh
Ranch Hand

Joined: Jan 04, 2008
Posts: 105
HI Rob

Thanks for your reply

Accordingly i modified the files

Hello.java******************

public class Hello
{
static
{
System.loadLibrary("hello");
}

public static native Student sayHello();
public static void main(String[] args)
{
Hello p = new Hello();

Student len = p.sayHello();

System.out.println("Name = " + len.name);
System.out.println("Age = " + len.age);
}

public class Student
{
private int age;
private String name;

public Student(int age, String name)
{
this.age = age;
this.name = name;
}

// the rest of the class
}

}

and Hello.c

#include <jni.h>
#include "Hello.h"
#include <stdio.h>

struct student
{
char *name;
int age;


}student1;

JNIEXPORT jobject JNICALL
Java_Hello_sayHello(JNIEnv *env, jclass cls)
{

jmethodID constructor;
jvalue args[2];
jobject object;


cls = (*env)->FindClass(env, "Student");

constructor = (*env)->GetMethodID(env, cls, "<init>", "(ILjava/lang/String V");

args[0].i = 23;
args[1].l = (*env)->NewStringUTF(env, "Jack");
object = (*env)->NewObjectA(env, cls, constructor, args);

return object;
}

Hello.h

contains

JNIEXPORT jobject JNICALL Java_Hello_sayHello
(JNIEnv *, jclass);

Now when i run the application using java hello

My JVM Crashes
getting the following error messages

"An Unexpected Error has been detected by Hotspot Virtual Machine............"

I dont know where i am doing wrong.please help
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19697
    
  20

The full classname is not Student - it is Hello$Student (since it's an inner class).

Because of this, FindClass will not find the class and return NULL. It also throws a ClassNotFoundException, but the problem with native code is - it doesn't return immediately after throwing an exception but only after the current function has finished. Your error is thrown earlier because of a native "NullPointerException".

Now I've changed the class name, and it can't find the constructor now. If I make the class static it works.

Now I've also tried to make the class non-static and the creation method as well - because you can't create an instance of a non-static inner class inside a static context of course. This didn't solve the issue though.

Therefore, I am sorry to say that I do not know how to create an instance of a non-static inner class in JNI.
 
GeeCON Prague 2014
 
subject: Return a Structure Object from C to Java Through JNI