我有以下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");
}
}
但我的结果没有差异。 instance获取非null值,info始终为null。我正在使用64位VM。我想知道问题是否可以是info字段的const修饰符?类型指针的struct字段中的const修饰符是否可以改变结构存储在内存中的方式?
类型指针的struct字段中的
const
修饰符可以改变结构存储在内存中的方式吗?
答案可能是,编译器依赖。对你的问题更重要的是const
如何影响本机访问字段的方式。无论你在Java方面做什么,一旦你初始化你的info
结构的core_st
字段,你就无法修改它。
这就是为什么你看到你在这里看到的东西:通过定义public info_st.ByReference info;
你正在用core_st
指针初始化NULL
结构并获得为该字段存储的内存地址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包装函数解决它。