如何使用JNI从C代码传递结构体到Java?

3

我需要传递一个结构体

   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代码。我已经搜索过,但没有找到完整的方法来实现。

谢谢。

3个回答

5
结构必须在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。有一个名为“从C传递C结构到Java”的章节,但随后它默默地解释了如何在Java类中反映所需的C结构并通过JNI将Java对象传递到C,这正是我的回答所说的。


3
你需要一个 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

1

您已经知道映射只能单向工作:您可以从C/C++访问Java类,但反之则不行。

但是重要的是要记住,这种映射涉及到显著的开销 - 在使用内存和CPU方面都是如此。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接