Link to home
Start Free TrialLog in
Avatar of sanjay_thakur
sanjay_thakur

asked on

Java and C struct

Hi,
I have a very basic question

what's the best way to read "C struct" in java

ex: I have a java client.
The client eastablishes a socket connection
to a server program (written in c)

now the client has to read the "c structures"
send by the server.

How do I deal with this.


Avatar of jasbro
jasbro
Flag of United States of America image

There are two ways I can think of immediately, one isn't platform independent, the other usually makes people run away screaming...

1.) You need to know the structure (byte by byte) of the the struct.  You will read byte by byte on the Java side, reorder bytes if necessary (depending on platform) and reconstruct the individual data items.  As I said, you will need to know the exact size in bytes of every member, and must have a decent understanding of the machine representation of that data type.

2.) Aaaaaaarrrrrrggggghhhh!!!!  You guessed it, JNI.  This can be done in two different ways...an add on to your server (implemented in Java with a bit of JNI code in between that maps the c struct to a java class) that then serializes the java class and sends it down your socket connection.  The other is just the just moves the c code to the client side...this has the same drawbacks as solution 1 if your client and server are different platforms.  The best is JNI on the server side.


Jason
Avatar of sanjay_thakur
sanjay_thakur

ASKER

I need some more details
Is there any general way so that

I can pack all the information in something similiar
to a structure and send it across to the server?

ex: if I have a structure
struct test
{
        char     *pw_passwd;          
     int     pw_uid;          
     int     pw_gid;          
     char     *pw_comment;    

}

How do I read all the values at once
and write all the data in the structure at once

I dont want to do it with bytes because
the structures I have are really hugh and
It will require a lot of parsing and rearranging.

basically can I make a Packet of some sort
so that I can send all the data at once
rather than in pieces

How complex will be JNI if I want to do this.


The JNI is not very complicated, but if you've never done JNI before, it can be a bit confusing.  The code for moving the struct in your comment would be similar to:

jclass cls;
jmethodID mid;
jstring str1,str2;

/*MyStruct is the Java class that looks similar to your struct, env is the JVM environment */
cls = (*env)->FindClass(env, "MyStruct");

/* "<init>" tells it to get me the method ID for the constructor with the given signature.
The signature (last arg) says the constructor takes two strings and two integers as parameters, and returns void...even though a constructor doesn't really return a value */
mid = (*env)->GetMethodID(env, cls, "<init>", "(Ljava/lang/String;Ljava/lang/String;II)V");

str1 = (*env)->NewStringUTF(env,s.pw_passwd);
str2 = (*env)->NewStringUTF(env,s.pw_comment);

/* Now that we have the method ID, we can call the constructor */
jobj = (*env)->NewObject(env, cls, mid, str1, str2, s.pw_uid, s.pw_gid);

/* if you implement the connection/send of the object in the Java class, you can just call that method, or you can implement the code to send it here, but you have to do a lot more work.  Make sure you make your Java class serializable, it will be easier to send. */  
ASKER CERTIFIED SOLUTION
Avatar of jasbro
jasbro
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hi I had a simple question

I am very new to JNI.
so bear with me

I have defined two java classes
passwd.class
passwdmain.class

In passwd class I have a native function
public native void commit();

I generate passwd.h
I have passwd.c where I implement commit() method
I generate a shared library Passwdlib.so


In passwdMain class I load the lbrary
System.loadLibrary("passwdLib")
create an Instance of Passwd class
like
passwd obj = new passwd();

call the native function

obj.commit();

but this gives me a "unsatified link error"

If I put everything in one class then it works fine

What do I need to do to make this work?
Is the library loaded in one class available to the other
class.


p.s :I tried loading the library in the passwd class also
but doesn't work

any suggestions?


 









First, is the exception coming on the loadLibrary call, or the call to your native method?  If it is coming on the load, then it can't find your library...if it is coming on the native method call, make sure that your native method exists in your library (if you used a c++ compiler, it may have mangled the name, also, the function name for the native function will probably be something like "Java_commit_1J".  Did you use javah to generate the header file, and then use the function declaration from that file?


p.s. sorry it took me so long to get to this, I have been on vacation...

Jason