【问题标题】:Is there a specific way to deal with const pointer members of a struct in JNA?是否有特定的方法来处理 JNA 中结构的 const 指针成员?
【发布时间】:2019-03-27 10:09:21
【问题描述】:

我有以下 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 始终为空。我正在使用 64 位 VM。 我想知道问题是否可能是 info 字段的 const 修饰符?指针类型的struct字段中的const修饰符可以改变struct在内存中的存储方式吗?

【问题讨论】:

    标签: java struct mapping jna


    【解决方案1】:

    指针类型的结构字段中的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 包装函数来解决它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-15
      • 2012-03-28
      • 1970-01-01
      • 2010-12-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多