【问题标题】:JNA multiple void pointers inside a C struct by reference通过引用在 C 结构中的 JNA 多个 void 指针
【发布时间】:2020-02-03 10:18:00
【问题描述】:

在我当前的项目中,我必须在 java 项目中实现原生 c 库的功能。 我正在使用 JNA。并且到目前为止取得了一些不错的成绩。 现在我陷入了以下问题。

我必须调用原生 c 函数:

int retrieveResult(ResultStruct * pResult)

结构体的定义如下:

typedef struct tag_ResultStruct
{
const void *pBuffer;
int sizeX;
int sizeY;
} ResultStruct;

在 Java 中,我创建了一个代表结构的类:

public class ResultStruct extends Structure{
   public Pointer pBuffer;
   public int sizeX;
   public int sizeY;

   @Override
   protected List<String> getFieldOrder(){
      return Arrays.asList(new String[] {"pBuffer", "sizeX", "sizeY"});
   }

   public ResultStruct(){

   }
}

我正在调用本机 C 方法

private interface MyCLib extends Library{
   MyCLib INSTANCE = Native.load("myclib", MyCLib.class);
   int retrieveResult(ResultStruct pResult);
}
ResultStruct resultStruct = new ResultStruct();
resultStruct.pBuffer = new Memory(bufferLen);
int res = MyCLib.INSTANCE.retrieveResult(resultStruct);

现在我可以从 sizeX、sizeY 和 pBuffer 中检索预期值了

resultStruct.pBuffer.getByteArray(0, bufferLen);

现在我像下面这样扩展我的结构:

typedef struct tag_ResultStruct
{
const void* pContext;
const void *pBuffer;
int sizeX;
int sizeY;
} ResultStruct;

还有我的 Java 结构:

public class ResultStruct extends Structure{
   public Pointer pContext;
   public Pointer pBuffer;
   public int sizeX;
   public int sizeY;

   @Override
   protected List<String> getFieldOrder(){
      return Arrays.asList(new String[] {"pContext", "pBuffer", "sizeX", "sizeY"});
   }

   public ResultStruct(){

   }
}

问题是,我不想使用 pContext。所以我不知道它应该有什么大小,因此我不初始化指针。 现在,当我尝试通过调用从缓冲区中检索值时:

resultStruct.pBuffer.getByteArray(0, bufferLen);

我没有从缓冲区中得到预期值。

问题

在使用JNA时,如何处理通过引用传递的结构内的多个动态内存字段? 可以在结构中保持未初始化的指针吗?

感谢任何帮助。提前谢谢你。

【问题讨论】:

  • 这里有一组非常酷的基于 JNA 的示例:eshayne.com/jnaex
  • 谢谢。我已经看过这些例子了。但是,当结构通过引用传递时,没有检索结构内部数组的示例。
  • 你的 API 告诉你应该为上下文指针传递什么?在分配具有必要值的Memory 对象时应该非常相似。
  • 请注意,结构填充可能在这里起作用。您的数据可能会发生对齐和读取不正确的情况。我建议玩#pragma packsetAlignType(ALIGN_NONE);。如果您无法访问(库的)源,最好使用JNI 访问它,您可以更好地控制细节。您可以决定(在代码的本机部分内)您的数据将如何在 CJava 之间精确映射。

标签: java c pointers struct jna


【解决方案1】:

感谢所有回答我问题的人。你让我走上了正轨。

回答

这是我的问题的答案。也许它可以帮助遇到相同或类似问题的其他人。

问题

在我使用的库(Basler 的 Pylon C API)中,提到您必须注册一个或多个输出缓冲区。这是通过分配缓冲区并注册该数组的指针来完成的。

通常我将字节数组 (byte[] buffer = new byte[size]) 映射到 uchar* 或 void* 缓冲区。当缓冲区直接填充到您的 c 函数中时(就像在 Oo.oO 给我的示例中一样),这是有效的。

但在我使用的 API 的上下文中,指针在注册后稍晚会被填充(当图像数据可用时,它会被填充)。 我不是专家,但我认为 java 字节数组不像真正的指针那样工作。

解决方案

我将 Java 中的缓冲区分配更改为

Pointer pBuffer = new Memory(size)

并在注册时将此指针映射到 void* 缓冲区指针。 现在缓冲区指针按预期工作,我可以稍后通过使用检索缓冲区的内容

byte[] data = pBuffer.getByteArray(0, size)

当函数retrieveResult(...)返回的指针位于结构体中时,这也有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-28
    • 1970-01-01
    • 2015-01-04
    • 1970-01-01
    • 2011-09-15
    相关资源
    最近更新 更多