• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • paul wheaton
  • Jeanne Boyarsky
  • Ron McLeod
Sheriffs:
  • Paul Clapham
  • Liutauras Vilda
  • Devaka Cooray
Saloon Keepers:
  • Tim Holloway
  • Roland Mueller
Bartenders:

Return a Structure Object from C to Java Through JNI

 
Ranch Hand
Posts: 105
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
 
Sheriff
Posts: 22821
132
Eclipse IDE Spring Chrome Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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 ]
 
Ajay Singh
Ranch Hand
Posts: 105
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 22821
132
Eclipse IDE Spring Chrome Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
It's just like a fortune cookie, but instead of a cookie, it's pie. And we'll call it ... tiny ad:
Smokeless wood heat with a rocket mass heater
https://woodheat.net
reply
    Bookmark Topic Watch Topic
  • New Topic