java – JNA. Creating a structure from a pointer

Question:

Good afternoon, colleagues!
There was a need to work closely with WinApi from Java. I don't want to use JNI because of laziness to switch between environments, compilers, etc. – decided to use the well-known JNA framework. The essence of the problem is as follows:

There is a wonderful function GetIfTable which has the following signature:

DWORD GetIfTable(
  _Out_   PMIB_IFTABLE pIfTable,
  _Inout_ PULONG       pdwSize,
  _In_    BOOL         bOrder
);

As you can see, it works with the MIB_IFTABLE structure , which looks like this:

typedef struct _MIB_IFTABLE {
  DWORD     dwNumEntries;
  MIB_IFROW table[ANY_SIZE];
} MIB_IFTABLE, *PMIB_IFTABLE;

If you read MSDN about this function, you can see an interesting way of using it:

  1. We pass to the function the structure created by default and its size (or null and dwSize = 0 ) in response, the function will return us a buffer error and write to dwSize the number of bytes of memory that must be allocated to store the output result.
  2. We allocate memory and call the method again. It returns 0 – everything is ok. We take the resulting array of structures and work on it.

With regard to Java and JNA, in this case, a problem arises – it is impossible to declare an array of unknown length in the structure, which means that you will have to work with pointers (PS> I will immediately make a reservation if you work not with pointers, but with instantiations of structures, indicating, for example, the table array equal to 1000 elements, then everything will work more or less correctly).

We declare structures and functions:

class MIB_IFTABLE extends Structure {
        public static class ByReference extends MIB_IFTABLE implements Structure.ByReference {}
        public static class ByValue extends MIB_IFTABLE implements Structure.ByValue { }

        public WinDef.DWORD dwNumEntries = new WinDef.DWORD();   //Количество интерфейсов в массиве
        public Pointer table = Pointer.NULL;


        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList(new String[]{"dwNumEntries", "table"});
        }

        public MIB_IFTABLE() {
        }

        public MIB_IFTABLE(Pointer p) {
            super(p);
        }
    }

    int GetIfTable(Pointer pIfTable, ULONGByReference pwdSize, WinDef.BOOL bOrder);

Well, let's try to work with all this:

Pointer pIfTable = Pointer.NULL;
WinApiHelper helper = WinApiHelper.INSTANCE;

WinDef.ULONGByReference dwSize = new WinDef.ULONGByReference(new WinDef.ULONG(0));
int res = helper.GetIfTable(pIfTable, dwSize, new WinDef.BOOL(false));
pIfTable = new Memory(dwSize.getValue().longValue());
res = helper.GetIfTable(pIfTable, dwSize, new WinDef.BOOL(false));

WinApiHelper.MIB_IFTABLE table = new WinApiHelper.MIB_IFTABLE(pIfTable);

And here comes the unexpected – there is no data in the table ! Those. the structure was not created and was unfilled at the pointer passed to it. Moreover, if you look at the data by the pIfTable pointer, then they are very much there, but I can't get to them normally. How to be?

Answer:

After creating the structure by pointer, the read() method had to be executed.

Scroll to Top