在JNA中是否有处理const指针成员的特定方法?

时间:2019-03-27 10:09:21

标签: java struct mapping 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字段始终为空(指向零的指针)。 如果将 jna.memory_dump 选项设置为true,则对core_st.toString()的任何调用都将始终返回相同的结果:

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

看来,指向 info 结构的指针不在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");
    }
}

但是我的结果没有差异。 instance 获取非空值,而 info 始终为null。我正在使用64位VM。 我想知道问题是否可能是 info 字段的 const 修饰符?可以在指针类型的struct字段中使用const修饰符来更改该结构在内存中的存储方式吗?

1 个答案:

答案 0 :(得分:0)

  

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

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

这就是为什么您在这里看到的内容:通过定义public info_st.ByReference info;,您可以使用指向core_st的指针来初始化NULL结构,并获取内存地址{{ 1}}为该字段存储。使用API​​访问该字段时,您无法更改内存地址,因为它被卡住了。

您会看到与使用默认值(0)的0x0进行初始化相同的结果。

解决方案取决于API如何填充该值。如果在本机方面,long函数假定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结构中。根据{{​​1}}的内部工作原理(并且根据您的报告,这似乎可以在C端使用),这可能有效!

如果没有,也许发布有效的C代码将有助于确定是否还有其他JNA映射会有所帮助,或者您是否必须使用自己的自定义DLL包装函数来解决该问题。