繁体   English   中英

在 JNA 中传递参数

[英]Passing parameter in JNA

此代码填充生成的数据结构 SCANNER_FULL_PLUS_EX,然后调用 function ScanReadFull_PlusEx()。 两者都是由JNAerator生成的,应该创建一些文件,如 Scan_F.bmp 等。

对于 windows 上的64 位 java 10 6 位,字节 [512] 中的文件名无法正确传递给 dll。 大多数时候文件名是null

    public short SCANTEST(String fileName) {

        StringBuilder BitmapNameF = new StringBuilder();
        StringBuilder BitmapNameR = new StringBuilder();
        StringBuilder BitmapNameF_IR = new StringBuilder();
        StringBuilder BitmapNameR_IR = new StringBuilder();
        StringBuilder BitmapNameF_UV = new StringBuilder();
        StringBuilder BitmapNameR_UV = new StringBuilder();

        SCANNER_FULL_PLUS_EX m_ScanFullPlusEx = new SCANNER_FULL_PLUS_EX();

        m_ScanFullPlusEx.Version = 0;
        m_ScanFullPlusEx.BrightnessFront = 100;
        m_ScanFullPlusEx.ThresholdFront = 100;
        m_ScanFullPlusEx.BrightnessRear = 100;
        m_ScanFullPlusEx.ThresholdRear = 100;
        m_ScanFullPlusEx.BitsPerPixel = 8;
        m_ScanFullPlusEx.ScanMode = 2;

        m_ScanFullPlusEx.ScanModeIR = 0;
        m_ScanFullPlusEx.ScanModeUV = 0;

        m_ScanFullPlusEx.dwImageWidth = 0;
        m_ScanFullPlusEx.dwImageHeight = 0;

        m_ScanFullPlusEx.pImageFront = new NativeLong(0);
        m_ScanFullPlusEx.dwImageSizeFront = 0;
        m_ScanFullPlusEx.pImageRear = new NativeLong(0);
        m_ScanFullPlusEx.dwImageSizeRear = 0;
        m_ScanFullPlusEx.pIR_ImageFront = new NativeLong(0);
        m_ScanFullPlusEx.dwIR_ImageSizeFront = 0;
        m_ScanFullPlusEx.pIR_ImageRear = new NativeLong(0);
        m_ScanFullPlusEx.dwIR_ImageSizeRear = 0;
        m_ScanFullPlusEx.pUV_ImageFront = new NativeLong(0);
        m_ScanFullPlusEx.dwUV_ImageSizeFront = 0;
        m_ScanFullPlusEx.pUV_ImageRear = new NativeLong(0);
        m_ScanFullPlusEx.dwUV_ImageSizeRear = 0;

        BitmapNameF.append(fileName + "F.bmp");
        BitmapNameR.append(fileName + "R.bmp");
        BitmapNameF_IR.append(fileName + "F_IR.bmp");
        BitmapNameR_IR.append(fileName + "R_IR.bmp");
        BitmapNameF_UV.append(fileName + "F_UV.bmp");
        BitmapNameR_UV.append(fileName + "R_UV.bmp");

        m_ScanFullPlusEx.ImageNameRear = Native.toByteArray(BitmapNameR.toString());
        m_ScanFullPlusEx.ImageNameFront = Native.toByteArray(BitmapNameF.toString());
        m_ScanFullPlusEx.IR_ImageNameFront = Native.toByteArray(BitmapNameF_IR.toString());
        m_ScanFullPlusEx.IR_ImageNameRear = Native.toByteArray(BitmapNameR_IR.toString());
        m_ScanFullPlusEx.UV_ImageNameFront = Native.toByteArray(BitmapNameF_UV.toString());
        m_ScanFullPlusEx.UV_ImageNameRear = Native.toByteArray(BitmapNameR_UV.toString());

        // wrap in 512 buffer
        byte[] f1 = new byte[512]; for (int i=0; i<m_ScanFullPlusEx.ImageNameRear.length;i++) f1[i]=m_ScanFullPlusEx.ImageNameRear[i]; m_ScanFullPlusEx.ImageNameRear = f1;
        byte[] f2 = new byte[512]; for (int i=0; i<m_ScanFullPlusEx.ImageNameFront.length;i++) f2[i]=m_ScanFullPlusEx.ImageNameFront[i]; m_ScanFullPlusEx.ImageNameFront = f2;
        byte[] f3 = new byte[512]; for (int i=0; i<m_ScanFullPlusEx.IR_ImageNameFront.length;i++) f3[i]=m_ScanFullPlusEx.IR_ImageNameFront[i]; m_ScanFullPlusEx.IR_ImageNameFront = f3;
        byte[] f4 = new byte[512]; for (int i=0; i<m_ScanFullPlusEx.IR_ImageNameRear.length;i++) f4[i]=m_ScanFullPlusEx.IR_ImageNameRear[i]; m_ScanFullPlusEx.IR_ImageNameRear = f4;
        byte[] f5 = new byte[512]; for (int i=0; i<m_ScanFullPlusEx.UV_ImageNameFront.length;i++) f5[i]=m_ScanFullPlusEx.UV_ImageNameFront[i]; m_ScanFullPlusEx.UV_ImageNameFront = f5;
        byte[] f6 = new byte[512]; for (int i=0; i<m_ScanFullPlusEx.UV_ImageNameRear.length;i++) f6[i]=m_ScanFullPlusEx.UV_ImageNameRear[i]; m_ScanFullPlusEx.UV_ImageNameRear = f6;

        short ret = MB2Library.INSTANCE.ScanReadFull_PlusEx(ByteBuffer.wrap(Native.toByteArray(gPort.Global)), m_ScanFullPlusEx, MB2Library.SCAN_OUTPUT_FORMAT_FILE_BMP);

        return ret;
    }

C header 文件的结构。

typedef struct
{
        int Version;
        int BrightnessFront;
        int ThresholdFront;

        int BrightnessRear;
        int ThresholdRear;
        int BitsPerPixel;

        int ScanMode;   // Front/Rear/Front-Rear
        int ScanModeIR; // ( not yet implemented ) IR Front/Rear/Front-Rear
        int ScanModeUV; // ( not yet implemented ) UV Front/Rear/Front-Rear

        DWORD dwImageWidth;
        DWORD dwImageHeight;

        // Front CIS Image
        HANDLE pImageFront;
        DWORD dwImageSizeFront;

        // Rear CIS Image
        HANDLE pImageRear;
        DWORD dwImageSizeRear;

        // Front IR Image
        HANDLE pIR_ImageFront;
        DWORD dwIR_ImageSizeFront;

        // Rear IR Image
        HANDLE pIR_ImageRear;
        DWORD dwIR_ImageSizeRear;

        // Front UV Image
        HANDLE pUV_ImageFront;
        DWORD dwUV_ImageSizeFront;

        // Rear UV Image
        HANDLE pUV_ImageRear;
        DWORD dwUV_ImageSizeRear;

        // images path
        TCHAR ImageNameFront[512];
        TCHAR ImageNameRear[512];
        TCHAR IR_ImageNameFront[512];
        TCHAR IR_ImageNameRear[512];
        TCHAR UV_ImageNameFront[512];
        TCHAR UV_ImageNameRear[512];

} SCANNER_FULL_PLUS_EX;

typedef SCANNER_FULL_PLUS_EX *PSCANNER_FULL_PLUS_EX;

编辑1:

package mb2;

import java.util.StringTokenizer;

import java.util.Arrays;
import java.util.List;

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.NativeLibrary;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.ptr.ByReference;
import com.sun.jna.ptr.PointerByReference;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.ByteByReference;
import com.sun.jna.ptr.DoubleByReference;
import com.sun.jna.ptr.FloatByReference;
import com.sun.jna.ptr.LongByReference;
import com.sun.jna.ptr.NativeLongByReference;
import com.sun.jna.ptr.ShortByReference;

public class SCANNER_FULL_PLUS_EX extends Structure {
    public int Version;
    public int BrightnessFront;
    public int ThresholdFront;
    public int BrightnessRear;
    public int ThresholdRear;
    public int BitsPerPixel;
    /** Front/Rear/Front-Rear */
    public int ScanMode;
    /** ( not yet implemented ) IR Front/Rear/Front-Rear */
    public int ScanModeIR;
    /** ( not yet implemented ) UV Front/Rear/Front-Rear */
    public int ScanModeUV;
    public int dwImageWidth;
    public int dwImageHeight;
    /**
     * Front CIS Image<br>
     * C type : HANDLE
     */
    public NativeLong pImageFront;
    public int dwImageSizeFront;
    /**
     * Rear CIS Image<br>
     * C type : HANDLE
     */
    public NativeLong pImageRear;
    public int dwImageSizeRear;
    /**
     * Front IR Image<br>
     * C type : HANDLE
     */
    public NativeLong pIR_ImageFront;
    public int dwIR_ImageSizeFront;
    /**
     * Rear IR Image<br>
     * C type : HANDLE
     */
    public NativeLong pIR_ImageRear;
    public int dwIR_ImageSizeRear;
    /**
     * Front UV Image<br>
     * C type : HANDLE
     */
    public NativeLong pUV_ImageFront;
    public int dwUV_ImageSizeFront;
    /**
     * Rear UV Image<br>
     * C type : HANDLE
     */
    public NativeLong pUV_ImageRear;
    public int dwUV_ImageSizeRear;
    /**
     * images path<br>
     * C type : TCHAR[512]
     */
    public byte[] ImageNameFront = new byte[512];
    /** C type : TCHAR[512] */
    public byte[] ImageNameRear = new byte[512];
    /** C type : TCHAR[512] */
    public byte[] IR_ImageNameFront = new byte[512];
    /** C type : TCHAR[512] */
    public byte[] IR_ImageNameRear = new byte[512];
    /** C type : TCHAR[512] */
    public byte[] UV_ImageNameFront = new byte[512];
    /** C type : TCHAR[512] */
    public byte[] UV_ImageNameRear = new byte[512];
    public SCANNER_FULL_PLUS_EX() {
        super();
    }
    protected List<String> getFieldOrder() {
        return Arrays.asList("Version", "BrightnessFront", "ThresholdFront", "BrightnessRear", "ThresholdRear", "BitsPerPixel", "ScanMode", "ScanModeIR", "ScanModeUV", "dwImageWidth", "dwImageHeight", "pImageFront", "dwImageSizeFront", "pImageRear", "dwImageSizeRear", "pIR_ImageFront", "dwIR_ImageSizeFront", "pIR_ImageRear", "dwIR_ImageSizeRear", "pUV_ImageFront", "dwUV_ImageSizeFront", "pUV_ImageRear", "dwUV_ImageSizeRear", "ImageNameFront", "ImageNameRear", "IR_ImageNameFront", "IR_ImageNameRear", "UV_ImageNameFront", "UV_ImageNameRear");
    }
    public SCANNER_FULL_PLUS_EX(Pointer peer) {
        super(peer);
    }
    public static class ByReference extends SCANNER_FULL_PLUS_EX implements Structure.ByReference {

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

    };
}

欢迎来到字符编码的奇妙世界。

您仅使用带有String参数的Native.toByteArray() 这将返回:

与给定字符串等效的以 NUL 结尾的字节缓冲区,使用 getDefaultStringEncoding() 返回的编码。

在字符串和字节 arrays 之间进行转换时,不指定编码通常是一种不好的做法。 在这种情况下,您实际上确实需要默认系统编码,但指定它很有用,并且在此过程中,了解它在做什么。

默认的 Windows 编码是 UTF-16,它使用 16 位来表示字符(C 中的wchar_t )。 对于 ASCII 字符串,就像您正在使用的字符串一样,这意味着您的字节数组以交替的 0 字节和 8 位字符字节结束。 (请随意检测您的代码和 output Arrays.toString(f1)自己看看这个!)

C 结构使用TCHAR的 arrays 。 这可以是单个字节或两个字节,具体取决于您的编码(将匹配Native.toByteArray() )。

所以这里的默认编码很好,除了你需要知道那个编码是什么,以便正确调整你的结构。 当您可能需要 512-TCHAR arrays(1024 字节)时,您正在传递 512 字节 arrays。

但是,JNA 结构必须知道它们的总字节大小,并且TCHAR未映射到 JNA 中。 因此,您必须计算出CHAR_WIDTH并将 512 乘以结构中的该值。 (在 JNA 源代码中搜索CHAR_WIDTH以获得大量示例。)

(编辑 1)

感谢您提供 JNA 映射。 通常,当 JNA 映射的函数/结构行为不端时,首先要查看的是类型映射。 在您的情况下,除了上述错误的TCHAR映射到byte之外,您还将HANDLE映射为NativeLong 这在 Windows 上不起作用: HANDLEPointerType扩展,并且指针匹配操作系统位数,64 位 Windows 上的 64 位也是如此。 另一方面,Windows LONG (因此在 Windows 上为NativeLong )始终是 32 位类型。

总而言之,您需要(至少)以下更改:

  1. HANDLE类型更改为 map 为 JNA 的WinNT.HANDLE class

  2. 更改TCHAR字节宽度以匹配字符宽度。 一种方法是将其插入 class 的顶部(或项目中的任何位置,公开,以便访问):

     private static final int CHAR_WIDTH = Boolean.getBoolean("w32.ascii")? 1: 2;

然后在您的byte[]声明中,乘以512 * CHAR_WIDTH以获得正确的宽度。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM