C结构体转换为Java JNA结构体(结构体指针)

3

我在基于C/C++结构体的JNA结构中遇到了问题。nScreenIndex、uVendorID、uProductID和uVersionNumber字段看起来没问题,但在它们后面是奇怪的字节。我的主要目标是“提取”pMonitor字段。 pMonitor声明和MONITOR实现是否正确?

C/C++原始代码:

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;

以及Java/JNA代码:

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 {
    };
}

pCWndBeamHandler 应该是 Pointer,而不是 PointerByReference。你还应该为每个 Structure 添加一个基于 Pointer 的构造函数,在 super() 之后调用 Structure.read()(这不是必要的,但可以避免不必要的额外内存分配)。 - technomage
1个回答

2

你说得非常接近了。

在Java的SCREEN类中,你需要将pMonitor定义为:

    public MONITOR.ByReference pMonitor;

根据常见问题解答,应该如何使用Structure.ByReference?Structure.ByValue?Structure[]?

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

作为补充说明:
当我使用mingw编译的dll进行存根操作时,我必须继承自StdCallLibrary而不是Library - 这可能对您没有影响,我只是提到这一点因为它影响了我的测试。

谢谢,现在它完美运行了。出现了两个问题:缺少“.ByReference”和结构体中的错误(默认)数据对齐。 我不得不将MONITOR更改为MONITOR.ByReference,并将super()更改为super(ALIGN_NONE)。 ALIGN_NONE在结构体上不设置对齐,将所有字段放置在最近的1字节边界上。 - jakson
C++代码中没有任何指示它使用8位打包的内容,但很高兴它对您有效。像这样改变打包规则是相当罕见的 - 在提到的C++接口中没有任何表明这种情况的内容。 - Anya Shenanigans
我没有C/C++源代码 - 我只有*.dll和*.h文件,但看起来Elo Touch Solutions开发人员在其触摸屏API中使用1字节对齐。 - jakson
顺便问一下:是否有办法为 JNA 库中的所有数据结构设置全局内存字节对齐方式(*.dll Java 包装器)? 目前,我正在使用非常笨拙的方式来实现这一点 - 我在每个结构体中都设置了数据对齐方式 (super(ALIGN_NONE))(在单独的文件中有很多结构体)。 http://stackoverflow.com/questions/36809144/how-to-set-global-memory-byte-alignment-for-all-structures-in-jna-library - jakson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接