简体   繁体   中英

how to pass structure from c code to java using Jni

I have to pass a structure

   struct Info {
    u_int8_t timestamp[8];
    u_int32_t  a;
    u_int32_t  b;
    u_int32_t  c;
    ActiveInfo activeInfo[MAX_ACTIVE_SET];

   };

 struct ActiveInfo
{
   u_int8_t  is_reference;
   u_int16_t p;
   u_int32_t q;
    u_int8_t  r;
   u_int8_t  s;
  };
  typedef struct ActiveInfo ActiveInfo;

I want to pass this (Info) structure to my java code.I have goggled,but not get complete ways to do this.

Thanks.

The structure must be defined at Java side, as a class with members. The fact is that JNI allows C to access Java objects, but not Java to access C objects (structs) . So if you want to "pass" something through JNI and have it accessible on both sides, it must be a Java object, then qualified as jobject in the interface. From C side then, you have two options:

  • either access the members directly with GetFieldID() and Get/Set<Type>Field , though it's more complicated with arrays (you got some i see)
  • or create Java methods in that class for filling up and reading in simplified fashion, and invoke them with Invoke<Retval>Method

It depends on design of your data storage. You perhaps want only one side (C or Java) to read and the other to write, which can be reflected in the design conveniently.

Edit:

Example can be found at site pointed out by @asgoth : www.steveolyo.com . There is a chapter named "Passing C Structures from C to Java" but then it silently explains how to reflect requried C structure in Java class and pass Java object into C via JNI - which is exactly what my response says.

You need a JNIEXPORT:

JNIEXPORT jint JNICALL 
Java_FillCStruct
(
   JNIEnv *env, 
   jclass obj, 
   jobject    info      // EntryInformation object instantiation
)
{
   testInfo entryInfo;
   jclass clazz;
   jfieldID fid;
   jmethodID mid;

   GetInfo(entryInfo);   // fills in the entryInfo

   clazz = (*env)->GetObjectClass(env, info);
   if (0 == clazz)
   {
      printf("GetObjectClass returned 0\n");
      return(-1);
   }
   fid = (*env)->GetFieldID(env,clazz,"index","I");

   // This next line is where the power is hidden. Directly change
   // even private fields within java objects. Nasty!
   (*env)->SetIntField(env,info,fid,testInfo.index); 
...

Here is a site with some examples: http://www.steveolyo.com/JNI/JNI.html

You already know that the mapping works only one way: you can access a Java class from C/C++, but not vice versa.

But it's also important to remember that such mapping involves significant overhead - both in memory used, and in CPU.

Therefore it may be wize to give up on complete transparency. For example, if you only need to read activeInfo[n].s, you can write a native method getais(int n). Or uou can receive the whole structure in java as a DirectByteBuffer, calculate the required offset, and manipulate the value directly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM