如何使用Jni将结构从c代码传递给java

时间:2012-12-21 10:34:37

标签: java android-ndk java-native-interface

我必须传递一个结构

   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;

我想将此(Info)结构传递给我的java代码。我已经使用goggled,但没有完全的方法来实现这一点。

感谢。

3 个答案:

答案 0 :(得分:4)

结构必须在Java端定义,作为具有成员的类。 事实上,JNI允许C访问Java对象,但不允许Java访问C对象(结构)。所以,如果你想"通过"通过JNI并且可以在两端访问它,它必须是一个Java对象,然后在界面中被限定为jobject。从C侧开始,您有两种选择:

  • 可以使用GetFieldID()Get/Set<Type>Field直接访问成员,但数组更复杂(我看到了一些)
  • 或在该类中创建Java方法以简化方式填写和阅读,并使用Invoke<Retval>Method
  • 调用它们

这取决于您的数据存储设计。您可能只想要一面(C或Java)阅读而另一面要写,这可以方便地反映在设计中。

修改

示例可以在@asgoth指出的网站上找到:www.steveolyo.com。有一章名为&#34;将C结构从C传递到Java&#34;但后来它静静地解释了如何在Java类中反映所需的C结构,并通过JNI将Java对象传递给C - 这正是我的回答所说的。

答案 1 :(得分:2)

你需要一个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); 
...

这是一个包含一些示例的网站: http://www.steveolyo.com/JNI/JNI.html

答案 2 :(得分:1)

您已经知道映射只能以一种方式工作:您可以从C / C ++访问Java类,但反之亦然。

但同样重要的是要记住,这种映射涉及很大的开销 - 无论是在内存中还是在CPU中。

因此,放弃完全透明度可能是错误的。例如,如果您只需要读取activeInfo [n] .s,则可以编写本机方法getais(int n)。或者你可以在java中接收整个结构作为DirectByteBuffer,计算所需的偏移量,并直接操纵该值。