I have the following C structure:
typedef struct {
void *instance;
const info_st *info;
} core_st;
Which I map to the following Java Class using JNA:
public class core_st extends Structure {
public Pointer instance;
public info_st.ByReference info;
@Override
protected List<String> getFieldOrder() {
return Arrays.asList("instance", "info");
}
}
I also have the following function taken from a dll:
uint32_t open_core(uint32_t core_id, core_st **core);
And the relative JNA mapping:
int open_core(int core_id, core_st[] core);
Finally, I wrote a java program that calls the function this way:
core_st[] cores = new core_st[1];
MyLibrary.INSTANCE.open_core(0, cores);
The function should populate cores[0]
members with the result of the "open" operation. In particular, the two fields are two pointers to something else. What happens is that the void *instance
field is always correctly populated, but the info
field is always null (a pointer to zero). If I set the jna.memory_dump option to true, any call of core_st.toString()
returns always the same result:
memory dump
[70cb64e7]
[fd7f0000]
[00000000]
[00000000]
It looks like the pointer to the info structure is not in the memory read by the JNA. The same call, performed by a similar C program, works fine, both pointers are correctly populated. I also tried to change the core_st mapping, just for test purposes:
public class core_st extends Structure {
public long instance;
public long info;
@Override
protected List<String> getFieldOrder() {
return Arrays.asList("instance", "info");
}
}
But I got no differences in the result. instance gets a non-null value, and info is always null. I am working with a 64bit VM. I was wondering if the problem could be the const modifier of the info field? Can the const modifier in a struct field of type pointer change the way the struct is stored in memory?
Can the
const
modifier in a struct field of type pointer change the way the struct is stored in memory?
The answer is maybe , compiler dependent. More important to your question is how const
affects the way the field is accessed on the native side. No matter what you do on the Java side, once you initialize the info
field of your core_st
structure, you can not modify it.
And that is why you are seeing what you're seeing here: by defining public info_st.ByReference info;
you are initializing the core_st
structure with a pointer to NULL
and getting the memory address 0x0
stored for that field. When accessing that field using the API, you can't change the memory address, it's stuck.
You see the same results initializing it as a long
with the default value (0).
The solution depends on how the API populates that value. If, on the native side, the open_core
function assumes that the info
field is already initialized with a pointer to an allocated structure, and just changes the values at the pointed-to memory, you're all set. You just need to initialize that field when you first instantiate the structure.
You don't tell me anything about what *info
points to, so the answer is different depending on whether it's an array of info_st
structures or a single structure. If it's a single structure, you have:
public class core_st extends Structure {
public Pointer instance;
public info_st.ByReference info = new info_st.ByReference();
}
This will allocate the appropriate memory here for an info_st
structure and store the read-only pointer in your core_st
structure. Depending on the inner workings of open_core()
(and based on your report that this seems to work on the C side), this may work!
If not, perhaps posting the working C code would help determine whether there's another JNA mapping that would help or if you have to work around it with your own custom dll wrapper function.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.