我具有以下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修饰符来更改该结构在内存中的存储方式吗?
答案 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包装函数来解决该问题。