• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 448
  • Last Modified:

JNI and passing back structures from a shared library

I have a C-library that my java will call (through JNI)  that passes a structure by reference.  This is a commercial shared library that I have to create another shared library to be called from.  It would look something like:

typedef struct _list {
  int    value;
  int    flag;
} ALIST;

typedef struct _output {
  char   outStr[50];
  ALIST listing;
} AOUTPUT;

int c_library_call(AOUTPUT &output)
{
...
}

I believe I need to make a class for the java side that holds the same information that the C structures do.  

public class ALIST
{
  int value;
  int flag;
}

public class AOUTPUT
{
  String  outStr;
  ALIST   listing;
}

# This native call will then call the actual library call that is in the commercial # library.
public static native int my_shared_lib(AOUTPUT output);

In the JNI interface (my_shared_lib) , how do I get the data from the structure that was returned from the c_library_call into my java class.

Thanks in advance for your help.
0
gekanger
Asked:
gekanger
  • 8
  • 7
1 Solution
 
mbormannCommented:
hello, am doing some JNI at the mmt.

so I can only hlp u out with procedure abt how to go abt it

First u call the Java objects native method (I assume that u want to call Native code first from Java )
which in turn will call the actual native code which will get that struct etc...

now u should have other 'normal' methods which u can call as this calss structyre says.

class JavaToJNIInterface
{

//pls keep it instance data if possible,not static
public int native your_shared_lib(Object1 o);//is thgis AOUTPUT ?

public int constructObjectFromRawData(String outStr,int value,int flag )
{
//make ALIST
//make AOUTPUT here

//or u can make them in 'C' and pass them here,it's ur choice
}

}

public class ALIST
{
int value;
int flag;
}

public class AOUTPUT
{
String  outStr;
ALIST   listing;
}

code like this will call ur Java code from 'C'

JNIEnv *env;
jclass cls;
jobject theObj;

//one/two denote package structure

   cls = (*env)->FindClass(env, "one/two/JavalLogin");
    if (cls == 0) {
        fprintf(stderr, "Can't find JavalLogin class\n");
        exit(1);
    }

theObj = (*env)->AllocObject(env, cls);

pls note that JNI allows 2-way communication

in addition to the JNI JavaSoft tutorial See these
This is one of the Best and I used it at Start
http://home.pacifier.com/~mmead/cs510jip/jni/ 

look at CodeGuru's Links to other good sites.
http://codeguru.developer.com/java/JNI/index.shtml

this one is repeating everything they tell but for beginners it looks good.                      http://herzberg1.ca.sandia.gov/JavaCourse/Java_1_1-Week5.html

hope it hepled u
0
 
mbormannCommented:
note the int in constructObjectFromRawData() is required to signal ur 'C' code that everything went fine, Keep it in ur final implementation also.
0
 
mbormannCommented:
no response from you?
0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 
gekangerAuthor Commented:
mbormann,

I got your responce and thanks.  I was using GetObjectClass and Get/Set<type>Field which gets kind of like a pointer back to the field in the class that called the native call.  The Set portion actually sets the values up in the java.  This worked fine for me and performed as if I was passing the class by reference (like C does).  I thought about calling a java method but this seemed easier to implement at the time.  Thanks for your comments though.

Glenn
0
 
shaveriCommented:
0
 
gekangerAuthor Commented:
shaveri,

Thanks but I'm not looking for examples when Strings or very simple Structures are passed back.  I understand how you get a pointer (C term) back to an object and then get the fields within the class.  The specific fields are then set.  The problem I have is how do you get to a sub-class and then set those fields.  For example:

public class Person
{
  String name;
  String address;
}

public class List
{
  int    index;
  Person aPerson;
}

If I have a native call like:

call_C_wrapper(List aList);

I would use GetObjectClass to get a jclass to the actual object passed in.  How do I get to the Person class contained within List inside the wrapper.  If you need a better example I will provide it.  

Thanks
0
 
mbormannCommented:
Glenn,
ur problem us not to get to a 'subclass' but a composed class Person inside List.I will try today /tommorrow wehn i can steal some time off.
0
 
gekangerAuthor Commented:
Amit,

Yea...I'm sure the terms I'm using are incorrect.  The key thing I'm looking for is how to get to a class that is inside another class (I called it a sub-class).  Thanks for your help with this.
0
 
mbormannCommented:
Glenn,
I really cant do the whole thing end to end but maybe u can ?Do tell me how it goes ,

Bye Amit

This is teh Java example

public class HelloWorld
{
    public native void display(List listClass);

    static
      {
        System.loadLibrary("hello");
    }
   
    public static void main(String[] args)
      {
            List listClass=new List();
            listClass.oneInt=100;
            listClass.person=new Person();
            listClass.person.bool=true;
            
        new HelloWorld().display(listClass);
    }
      
      //Use this to access the type signature from JNI
      //comment them out later
      public static List accessFromC;
      public static Person person;
}


class List
{
      public int oneInt;
      public Person person;
}

class Person
{
      public boolean bool;
}

Now the way to do it in 'C' is i got this heaeder when I gave
javah -jni HelloWorld


/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloWorld */

#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     HelloWorld
 * Method:    display
 * Signature: (LList;)V
 */
JNIEXPORT void JNICALL Java_HelloWorld_display
  (JNIEnv *, jobject, jobject);

#ifdef __cplusplus
}
#endif
#endif


Now the 'C' would be
#include <jni.h>
#include "HelloWorld.h"
#include <stdio.h>

JNIEXPORT void JNICALL Java_HelloWorld_display
(JNIEnv *env, jobject obj,jobject obj1)
{
      //get the handle to the class of List here
      jclass cls = (*env)->GetObjectClass(env, obj1);
      jfieldID fid;
      jboolean personAccess;

      //fid is Id of Person object,which is public and inside class List
      fid = (*env)->GetFieldID(env, cls, "person", "LPerson;");

      if (fid == 0)
      {
            return;
      }
      
      //do further processing to access the boolean
      //field inside class Person

      //i.e get the field ID of Boolean field ,change it to jboolean?
      //I am not sure abt this.

      return;
}

this is the signature analysis of the HelloWorld class whicxh we use for getting the field ID of class Person since it is a instance field inside the class List.

Note I think that the second jobject in the signature
>>>>>JNIEXPORT void JNICALL Java_HelloWorld_display
(JNIEnv *env, jobject obj,jobject obj1) is the actual object of the passed List ,so I did accordingly

D:\native>javap -s -p HelloWorld
Compiled from HelloWorld.java
public synchronized class HelloWorld extends java.lang.Object
    /* ACC_SUPER bit set */
{
    public static List accessFromC;
        /*   LList;   */
    public static Person person;
        /*   LPerson;   */
    public native void display(List);
        /*   (LList;)V   */
    public static void main(java.lang.String[]);
        /*   ([Ljava/lang/String;)V   */
    public HelloWorld();
        /*   ()V   */
    static static {};
        /*   ()V   */
}

D:\native>

I consulted the following pages for reference

http://java.sun.com/docs/books/tutorial/native1.1/implementing/method.html

http://java.sun.com/docs/books/tutorial/native1.1/implementing/example-1dot1/FieldAccess.c

http://java.sun.com/docs/books/tutorial/native1.1/implementing/field.html

Regards
Amit
0
 
gekangerAuthor Commented:
Thanks Amit,

This is about the same as what I had been doing previously.  I wasn't sure if you could use the signature of "LPerson;" to get the structure within another structure.  I had used javap -s -p to get the signatures but thought it just wasn't resolving those values.  Thanks again.
0
 
mbormannCommented:
isn't this a cool newsgroup? It has also solved my queries when I was pressed for time and wanted help badly.
:-)
0
 
mbormannCommented:
another thing i found out right now was that if ur class is contained within a package then the signature changes.

like string is in java.lang

Ljava/lang/String;

Person is in com.baz

Lcom/baz/Person;
0
 
gekangerAuthor Commented:
thanks again
0
 
gekangerAuthor Commented:
This is for anyone wishing to have a more complete example.  If you want more information on this, email me and I'll send you a better example
0
 
mbormannCommented:
put ur Email ID in ur profile or here ,how will the others contact u otherwise?
:)
0
 
gekangerAuthor Commented:
Thanks.  I thought that my profile had it listed...but I guess not.

gekanger@hotmail.com
0

Featured Post

The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

  • 8
  • 7
Tackle projects and never again get stuck behind a technical roadblock.
Join Now