java - 如何使用 JNA 将包含结构数组的结构传递给 C++ 函数?

标签 java windows struct jna

我正在构建一个 Java 应用程序,该应用程序使用 JNA 与特定制造商的 API 进行通信。我映射了大量的函数调用并且已经在工作,但是有两个函数让我有些悲伤。

这两个函数都来回传递数据结构来配置设备。该结构内部有一个嵌套的数据结构数组。

原生定义:

VISION_API_DECL BOOL VISION_API SetDeviceParameters( DWORD DeviceID, DeviceParameters  DeviceParam );
VISION_API_DECL BOOL VISION_API GetDeviceParameters( DWORD DeviceID, DeviceParameters  *DeviceParam );

我用 Java 声明了它们,如下所示:

public interface Driver extends Library {
    ...
    public boolean SetDeviceParameters(int DeviceID, DEVICE_PARAMETERS DeviceParam);
    public boolean GetDeviceParameters(int DeviceID, DEVICE_PARAMETERS DeviceParam);
    ...
}

这些函数调用似乎可以工作。当我调用这两个函数时,JNA 不会引发异常。当我调用 GetDeviceParameters 方法并打印出该结构时,我看到其中大部分内容都填充了我认为是设备默认配置的数据。但是,当我使用刚刚从 get 调用返回的相同数据调用 SetDeviceParameters 方法时,设备会返回一个错误,指出参数错误。

我如何知道我是否正确映射了结构?

native :

typedef struct _DeviceParameters
{
  BOOL bMICREnable;
  UINT nMICRFont;
  BOOL bMICRSaveSamples;
  UINT nMICRSpaces;
  char cRejectSymbol;
  UINT nReserved;
  BOOL bReserved;
  IMAGE_PROPERTIES  ImagePropertiesFront1;
  IMAGE_PROPERTIES  ImagePropertiesFront2;
  IMAGE_PROPERTIES  ImagePropertiesRear1;
  IMAGE_PROPERTIES  ImagePropertiesRear2;
  SNIPPET_PROPERTIES SnippetProperties[10];
  BOOL bPrintEnable;
  BOOL bOneDoc;
  UINT nFeedingMode;
} DeviceParameters;

typedef struct _SnippetProperties
{
  BOOL Enable;
  BOOL Front;
  Snippet Properties;
} SNIPPET_PROPERTIES;

typedef struct _Snippet
{
  UINT Xposition;
  UINT Yposition;
  UINT Width;
  UINT Height;
  UINT Orientation;
  UINT Color;
  UINT Compression;
  BOOL Millimeters;
} Snippet;

typedef struct _ImageProperties
{
  UINT Format;
  UINT Paging;
  UINT Resolution;
  UINT ColorDepth;
  UINT Threshold;
} IMAGE_PROPERTIES;

Java:

public class DEVICE_PARAMETERS extends Structure {
    public boolean bMICREnable;
    public int nMICRFont;
    public boolean bMICRSaveSamples;
    public int nMICRSpaces;
    public byte cRejectSymbol;
    public int nReserved;
    public boolean bReserved;
    public IMAGE_PROPERTIES ImagePropertiesFront1;
    public IMAGE_PROPERTIES ImagePropertiesFront2;
    public IMAGE_PROPERTIES ImagePropertiesRear1;
    public IMAGE_PROPERTIES ImagePropertiesRear2;
    public SNIPPET_PROPERTIES[] SnippetProperties = new SNIPPET_PROPERTIES[10];
    public boolean bPrintEnable;
    public boolean bOneDoc;
    public int nFeedingMode;

    @Override
    protected List getFieldOrder() {
        return Arrays.asList(
                "bMICREnable"
                , "nMICRFont"
                , "bMICRSaveSamples"
                , "nMICRSpaces"
                , "cRejectSymbol"
                , "nReserved"
                , "bReserved"
                , "ImagePropertiesFront1"
                , "ImagePropertiesFront2"
                , "ImagePropertiesRear1"
                , "ImagePropertiesRear2"
                , "SnippetProperties"
                , "bPrintEnable"
                , "bOneDoc"
                , "nFeedingMode"
        );
    }
}

public class IMAGE_PROPERTIES extends Structure {
    public int Format;
    public int Paging;
    public int Resolution;
    public int ColorDepth;
    public int Threshold;

    @SuppressWarnings("RedundantArrayCreation")
    @Override
    protected List getFieldOrder() {
        return Arrays.asList(
                new String[]{
                        "Format"
                        , "Paging"
                        , "Resolution"
                        , "ColorDepth"
                        , "Threshold"
                }
        );
    }
}

public class SNIPPET_PROPERTIES extends Structure {
    public boolean Enable;
    public boolean Front;
    public SNIPPET Properties = new SNIPPET();

    @Override
    protected List getFieldOrder() {
        return Arrays.asList("Enable", "Front", "Properties");
    }
}

public class SNIPPET extends Structure {

    public int Xposition;
    public int Yposition;
    public int Width;
    public int Height;
    public int Orientation;
    public int Color;
    public int Compression;
    public boolean Millimeters;

    @Override
    protected List getFieldOrder() {
        return Arrays.asList("Xposition"
                , "Yposition"
                , "Width"
                , "Height"
                , "Orientation"
                , "Color"
                , "Compression"
                , "Millimeters"
        );
    }
}

输出:

DEVICE_PARAMETERS(auto-allocated@0x16a25938 (520 bytes)) {
  boolean bMICREnable@0=false
  int nMICRFont@4=1
  boolean bMICRSaveSamples@8=false
  int nMICRSpaces@c=2
  byte cRejectSymbol@10=3f
  int nReserved@14=0
  boolean bReserved@18=false
  IMAGE_PROPERTIES ImagePropertiesFront1@1c=IMAGE_PROPERTIES(allocated@0x16a25954 (20 bytes) (shared from auto-allocated@0x16a25938 (520 bytes))) {
    int Format@0=0
    int Paging@4=0
    int Resolution@8=0
    int ColorDepth@c=0
    int Threshold@10=0
  }
  IMAGE_PROPERTIES ImagePropertiesFront2@30=IMAGE_PROPERTIES(allocated@0x16a25968 (20 bytes) (shared from auto-allocated@0x16a25938 (520 bytes))) {
    int Format@0=0
    int Paging@4=0
    int Resolution@8=0
    int ColorDepth@c=0
    int Threshold@10=0
  }
  IMAGE_PROPERTIES ImagePropertiesRear1@44=IMAGE_PROPERTIES(allocated@0x16a2597c (20 bytes) (shared from auto-allocated@0x16a25938 (520 bytes))) {
    int Format@0=0
    int Paging@4=0
    int Resolution@8=0
    int ColorDepth@c=0
    int Threshold@10=0
  }
  IMAGE_PROPERTIES ImagePropertiesRear2@58=IMAGE_PROPERTIES(allocated@0x16a25990 (20 bytes) (shared from auto-allocated@0x16a25938 (520 bytes))) {
    int Format@0=0
    int Paging@4=0
    int Resolution@8=0
    int ColorDepth@c=0
    int Threshold@10=0
  }
  SNIPPET_PROPERTIES SnippetProperties[10]@6c=[Lpanini.data.SNIPPET_PROPERTIES;@fb642f
  boolean bPrintEnable@1fc=false
  boolean bOneDoc@200=false
  int nFeedingMode@204=1
}
memory dump
[00000000]
[01000000]
[00000000]
[02000000]
[3f000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[00000000]
[01000000]
Device Error: Wrong device parameters <-- this is where I try to set params

最佳答案

您还没有包含方法声明,它应该如下所示(假设您没有在声明中简单地输入错误):

boolean SetDeviceParameters(int deviceID, DeviceParameters.ByValue params);
boolean GetDeviceParameters(int deviceID, DeviceParameters params);

确保在传递给 SetDeviceParameters() 方法时使用标记有 Structure.ByValue 的结构版本。您需要定义结构的 ByValue 版本。

public class DeviceParameters extends Structure {
    public ByValue extends DeviceParameters implements Structure.ByValue {
        public ByValue() { }
        public ByValue(Pointer p) { super(p); read(); }
    }
}

然后您可以将 struct * 转换为 struct,如下所示:

DeviceParameters dp = new DeviceParameters();
DeviceParameters.ByValue bv = new DeviceParameters.ByValue(dp.getPointer());

关于java - 如何使用 JNA 将包含结构数组的结构传递给 C++ 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29402840/

相关文章:

c++ - OpenGL 上的多线程渲染

windows - lua的字符串模式匹配为什么要这样做呢?

python - 为什么struct中第一个打包的数据是little endian,而其余的都是big endian?

c# - List<T> 和数组索引器有什么区别?

java - 如何将当前方法的参数放入列表中

为多个应用程序提供服务的 Java 缓存

java - 这个类有多少个方法?

windows - 通过 Cron 问题的 CakePHP 控制台

c - 将结构传递给采用 void* 类型变量的回调

java - com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException : Unknown column 'id_cita' in 'field list'