C struct to Java JNA Structure (pointer to struct)

2019-06-02 08:36发布

问题:

I have problem with JNA Structure based on C/C++ struct. Fields nScreenIndex, uVendorID, uProductID, uVersionNumber looks OK, but after them I see odd bytes. My main and only goal is to "extract" pMonitor fields. Are pMonitor declaration and MONITOR implementation correct?

C/C++ origin:

SCREEN* EloGetScreenByIndex (int nScreenIndex);

typedef struct SCREEN_TAG
{
    int               nScreenIndex;
    USHORT            uVendorID;     
    USHORT            uProductID;    
    USHORT            uVersionNumber;
    wchar_t           szDevicePath [MAX_PATH];
    HANDLE            hCalTouchThread;
    MONITOR*          pMonitor;
    LPVOID            pCWndBeamHandler;
    BOOL              bIrBeams;
} SCREEN;

typedef struct MONITORS_TAG
{
    int     elo_mon_num;
    int     x;
    int     y;
    int     width;
    int     height;
    DWORD   orientation;
    bool    is_primary;
} MONITOR;

and Java/JNA code:

SCREEN EloGetScreenByIndex(int nScreenIndex);

public class SCREEN extends Structure {
    public int nScreenIndex;
    public short uVendorID;
    public short uProductID;
    public short uVersionNumber;
    public char[] szDevicePath = new char[WinDef.MAX_PATH];
    public WinNT.HANDLE hCalTouchThread;
    public MONITOR pMonitor;
    public PointerByReference pCWndBeamHandler;
    public boolean bIrBeams;
    ...
}

public class MONITOR extends Structure {
    public int elo_mon_num;
    public int x;
    public int y;
    public int width;
    public int height;
    public int orientation;
    public byte is_primary;

    public MONITOR() {
        super();
    }

    @Override
    protected List<? > getFieldOrder() {
        return Arrays.asList("elo_mon_num", "x", "y", "width", "height", "orientation", "is_primary");
    }

    public MONITOR(Pointer peer) {
        super(peer);
    }

    public static class ByReference extends MONITOR implements Structure.ByReference {
    };

    public static class ByValue extends MONITOR implements Structure.ByValue {
    };
}

回答1:

You're so very close to right.

in the SCREEN class in java, you need to define pMonitor as:

    public MONITOR.ByReference pMonitor;

This is per the FAQ.

When should I use Structure.ByReference? Structure.ByValue? Structure[]?

typedef struct _outerstruct2 {
  simplestruct *byref; // use Structure.ByReference
} outerstruct2;  

As an addendum:

When I stubbed this up using a mingw compiled dll, I had to inherit from StdCallLibrary and not Library - this may not be the case for you, I'm just mentioning this as it affected my testing.