有没有一种特定的方法来处理 JNA 中结构的常量指针成员?



我有以下C结构:

typedef struct {
void           *instance;
const info_st  *info;
} core_st;

我使用 JNA 将其映射到以下 Java 类:

public class core_st extends Structure {
public Pointer instance;
public info_st.ByReference info;
@Override
protected List<String> getFieldOrder() {
return Arrays.asList("instance", "info");
}
}

我还从 dll 中获取了以下功能:

uint32_t open_core(uint32_t core_id, core_st **core);

以及相对的JNA映射:

int open_core(int core_id, core_st[] core);

最后,我编写了一个以这种方式调用函数的 java 程序:

core_st[] cores = new core_st[1];
MyLibrary.INSTANCE.open_core(0, cores);

该函数应使用"打开"操作的结果填充cores[0]成员。特别是,这两个字段是指向其他内容的两个指针。发生的情况是,void *instance字段始终正确填充,但info字段始终为 null(指向零的指针)。 如果我将jna.memory_dump选项设置为 true,则任何core_st.toString()调用始终返回相同的结果:

memory dump
[70cb64e7]
[fd7f0000]
[00000000]
[00000000]

看起来指向信息结构的指针不在 JNA 读取的内存中。由类似的 C 程序执行的相同调用工作正常,两个指针都正确填充。 我还尝试更改core_st映射,仅用于测试目的:

public class core_st extends Structure {
public long instance;
public long info;
@Override
protected List<String> getFieldOrder() {
return Arrays.asList("instance", "info");
}
}

但我在结果上没有区别。实例获取非空值,并且信息始终为空。我正在使用 64 位 VM。 我想知道问题是否可能是信息字段的常量修饰符?指针类型的结构字段中的 const 修饰符能否更改结构在内存中的存储方式?

指针类型的结构字段中的const修饰符可以更改结构在内存中的存储方式吗?

答案是也许,取决于编译器。 对于您的问题来说,更重要的是const如何影响在本机端访问字段的方式。 无论你在 Java 端做什么,一旦初始化了core_st结构的info字段,你就不能修改它。

这就是为什么你在这里看到你所看到的:通过定义public info_st.ByReference info;,你正在使用指向NULL的指针初始化core_st结构,并获取0x0为该字段存储的内存地址。 使用 API 访问该字段时,您无法更改内存地址,它已卡住。

您会看到相同的结果,将其初始化为默认值为 (0) 的long

解决方案取决于 API 如何填充该值。 如果在本机端,open_core函数假定info字段已经使用指向已分配结构的指针初始化,并且只是更改指向内存的值,则一切就绪。 您只需要在首次实例化结构时初始化该字段。

你没有告诉我任何关于*info指向什么,所以答案是不同的,这取决于它是info_st结构数组还是单个结构。 如果是单个结构,则具有:

public class core_st extends Structure {
public Pointer instance;
public info_st.ByReference info = new info_st.ByReference();
}

这将在此处为info_st结构分配适当的内存,并将只读指针存储在core_st结构中。 根据open_core()的内部工作原理(以及根据您的报告,这似乎适用于 C 端),这可能会起作用!

如果没有,也许发布工作 C 代码将有助于确定是否有另一个 JNA 映射会有所帮助,或者您是否必须使用自己的自定义 dll 包装器函数来解决它。

最新更新