如何使用 JNA 将包含结构数组的结构传递给 C++ 函数? [英] How do I pass a Structure that contains an array of Structures to a C++ function using JNA?

查看:68
本文介绍了如何使用 JNA 将包含结构数组的结构传递给 C++ 函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个 Java 应用程序,该应用程序使用 JNA 与特定制造商的 API 进行通信.我已经映射了大量函数调用并且已经在运行,但是有一对函数让我感到有些难过.

I am building a Java application that communicates with a particular manufacturer's API using JNA. I have a ton of function calls mapped and already working, but there are a pair of functions that have been giving me some grief.

这两个函数来回传递数据结构来配置设备.该结构中有一个嵌套的数据结构数组.

Both of these functions pass a data structure back and forth to configure the device. This structure has a nested array of data structures within it.

原生定义:

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

我在 Java 中像这样声明了它们:

I have them declared in Java like so:

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 方法时,设备返回一个错误,指出参数错误.

These function calls seem to work. JNA does not throw an exception when I call either of those functions. When I call the GetDeviceParameters method and print out the struct, I see most of it filled with data from what I would assume is the device's default configuration. However, when I call the SetDeviceParameters method using the same data just returned from the get call, the device returns an error saying the parameters are wrong.

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

本地:

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

推荐答案

你没有包含你的方法声明,它应该是这样的(假设你没有简单地在声明中打错字):

You haven't included your method declarations, which should look like this (assuming you haven't simply made a typo in the declaration):

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

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

Make sure that you use a version of the structure tagged with Structure.ByValue when passing to the SetDeviceParameters() method. You'll need to define a ByValue version of your structure.

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

然后您可以像这样从 struct * 转换为 struct:

You can then convert from struct * to struct like this:

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

这篇关于如何使用 JNA 将包含结构数组的结构传递给 C++ 函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆