【问题标题】:JNA: how to deal with unkown structs?JNA:如何处理未知结构?
【发布时间】:2013-08-01 14:55:46
【问题描述】:

如果我没记错的话,JNA Structure 依赖于其对应的 Java 类的公共字段来构建结构,该类应该扩展 Structure。我的问题是我需要传递一个事先不知道其声明的结构(假设它在运行时已知)。我只有Objects 的列表,C 库期望它作为(对 a 的引用)结构。我仍然可以使用 Structure 类还是必须手动构建一个 Memory 对象,自己处理大小、对齐/打包?

例如:

 /* native code */
 typedef struct mystruct {
     int x;
     float y;
 }  mystruct;

 void dosomething(mystruct * s) {
     s->y += s->x;
 }

在 Java 中:

 ...
 callFunctionWithSt("dosomething",
     new Object[]{Integer.valueOf(2),Float.valueOf(3.0)});
 ...

 void callFunctionWithSt(String funcName, Object[] structVals) {
     NativeLibrary nl = ...
     Pointer arg = ...  // or Memory ... or Structure
     // build structure
     for (Object objJava  : structVals) {
         valJna = convertFromJavaToJnaObject(objJava);
         // fill structure
     }
     f.invoke(arg);
 }

 Object convertFromJavaToJnaObject(Object) {
     // assume we know how to do this
 }

【问题讨论】:

  • 能否提供原生 API 示例?如果您的本机代码使用不透明的struct,则只有在所有操作都在struct* 上执行时才能这样做,在这种情况下,您可以使用PointerPointerType 并忽略它背后的内存。
  • 我需要完全按照通过引用传递结构时通常所做的事情。本机代码不是不透明的,只是我在编译时不知道结构。

标签: java c struct jna


【解决方案1】:

如果你不知道结构的内容,那么它被称为“不透明”。

对于不透明的struct *,可以使用com.sun.jna.Pointer来表示结构地址。

【讨论】:

  • 我知道内容,只是我在运行时才知道。要使用指针(我认为应该是内存),我需要自己完成结构所做的所有字段对齐计算。
  • 如果您只知道内容和运行时间,这是否意味着您必须即时计算内容的位置?或者你说的是多态性?
  • 您能否提供一个示例,说明如何将Pointer 与不透明的struct * 一起使用?特别是,您将如何创建Pointer
【解决方案2】:

您仍然可以使用Structure。像这样定义你的接口方法:

interface SomeLib {
    public static final SomeLib INSTANCE =
        (SomeLib) Native.loadLibrary("SomeLib", SomeLib.class);

    Pointer getSomeStruct();
}

然后当你调用它时,你就这样做:

Pointer someValue = SomeLib.INSTANCE.getSomeStruct();
// do something here to determine what type it is
SpecificStructure struct = new SpecificStructure(someValue);

【讨论】:

  • 这里假设struct是直接返回的,但是如果是引用返回呢?例如。 int getSomeStruct(struct *s)。这似乎是 OP 所说的,因为他提到“通过引用传递结构”。
  • 不,我发布的代码是通过引用进行的,这就是为什么这里有一个指针。如果直接返回,我不完全确定如何处理它,但我猜制作结构的 ByValue 子类是您需要这样做的提示。
  • 好吧,我对 C 术语不太熟悉,但我的意思是“作为参数”。也许我误解了OP。无论如何,我已经就这个主题提出了另一个问题here;如果您知道如何将其作为参数进行操作,请在此处分享。
  • 啊,作为参数你可以把Pointer放在参数里面。因为它是一个不透明的结构,你必须从其他地方得到它,可能是另一个函数,它也会将它作为指针返回,所以你只需保留它并将它按原样传递给另一个。然而,在我们的实际生产代码中,我们所做的是子类 PointerType,其名称与库头文件中的名称更匹配,然后将其放在所有方法上。这样一来,就更难搞砸并传递错误的东西了。
  • 不,我的意思是我试图调用的函数通过一个参数返回,我需要在不了解结构的情况下以某种方式创建指针。在 C 中你会做类似malloc(sizeof(SomeStruct)) 的事情(同样,不是 C 程序员),但我不确定如何在 Java 中做到这一点。请参阅我链接的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多