这段代码填充了一个生成的数据结构SCANNER_FULL_PLUS_EX,然后调用一个函数ScanReadFull_PlusEx()。这两个函数都是由 JNAerator 并应该创建一些文件,如Scan_F.bmp等。
对于 64位java 在windows 10 6-bit上,字节[512]中的文件名不能正确传递给dll。大多数情况下,文件名是 无效
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头文件。
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 {
};
}
欢迎来到奇妙的世界 字码.
你用的是 Native.toByteArray() 只有 String
参数。 返回
使用getDefaultStringEncoding()返回的编码,返回一个等价于给定字符串的NUL-terminalated字节缓冲区。
当在Strings和字节数组之间转换时,通常不指定编码是一种不好的做法。 在这种情况下,实际上你确实希望使用默认的系统编码,但指定这个编码是很有用的,而且,在这个过程中,你可以了解它在做什么。
默认的 Windows 编码是 UTF-16,它使用 16 位来表示字符 (wchar_t
在C语言中)。) 对于ASCII字符串,比如你正在使用的字符串,这意味着你的字节数组最终以交替的0字节和8位字符字节结束。 (你可以自由地测量你的代码,并输出 Arrays.toString(f1)
自己去看看吧!)。)
C结构使用数组的 TCHAR
. 这可以是一个单字节或两个字节,取决于你的编码(这将符合 Native.toByteArray()
).
所以这里的默认编码是没有问题的,只是你需要知道这个编码是什么,以便正确地确定结构的大小。 你传递的是512字节的数组,而你可能需要的是512-TCHAR数组(1024字节)。
然而,JNA结构必须知道它们的总字节大小,并且...。TCHAR
在JNA中没有映射。 所以你必须弄清楚 CHAR_WIDTH
并在结构中用该值乘以512。 (搜索JNA源码,可以找到 CHAR_WIDTH
的大量例子。)
(编辑1)
谢谢你提供JNA映射。一般来说,当一个 JNA 映射的函数结构出现错误时,首先要检查的是类型映射。 在您的例子中,除了不正确的 TCHAR
映射到 byte
如上所述,您已经将 HANDLE
作为 NativeLong
. 这在Windows上不起作用。HANDLE
在Windows上行不通:从 PointerType
和指针与操作系统位数相匹配,所以在64位Windows上是64位的。 在64位的Windows LONG
另一方面 NativeLong
在Windows上)始终是一个32位类型。
因此,总结一下,你需要(至少)做以下改动。
改变 HANDLE
类型来映射到JNA的 WinNT.HANDLE
阶层
更改 TCHAR
字节宽度来匹配字符宽度。 一种方法是在你的类的顶部插入这个(或者在你的项目中的任何地方,公共的,这样它就可以被访问)。
private static final int CHAR_WIDTH = Boolean.getBoolean("w32.ascii") ? 1 : 2;
然后在你的 byte[]
宣言,乘以 512 * CHAR_WIDTH
以获得正确的宽度。