JNA实践

JNA使用总结

  • 环境搭建

1. JDK版本的位数,必须与DLL的位数相配,否则回如下错误

"Exception in thread “main” Java.lang.UnsatisfiedLinkError: Unable to load library ‘RWBIF.dll’: 找不到指定的模块。"
2. JAVA DLL 路径指定

  • sample1:对应的DLL要放在编译的bin目录下
    public static String DEFAULT_NXT_DLL_NAME = "RWBIF";
    
    NxtService nxtServiceInstance = Native.loadLibrary(DEFAULT_NXT_DLL_NAME,
      NxtService.class);
    
    
  • sample2:指定绝对路径
    NxtManager.programName = "C:\\java\\code\\nxt_plus\\RWBIF.dll";
    NxtService nxtServiceInstance = (NxtService) Native.loadLibrary(NxtManager.programName, NxtService.class);
    

3.使用jar包

    // https://mvnrepository.com/artifact/net.java.dev.jna/jna  
	compile group: 'net.java.dev.jna', name: 'jna', version: '4.5.0'
  • JNA使用

1. Java 与JNA类型映射
http://java-native-access.github.io/jna/4.4.0/javadoc/overview-summary.html#structures
2. Java 与JNA基本类型映射

  • char(c,c++,8it) —> byte(java,8bit)
    C++
```
typedef struct _tag_RWBIF_PANELIDINFO_EX
{
    TCHAR szBarcode[68];//typedefine char TCHAR
    INT nLane;
} RWBIF_PANELIDINFO_EX, *PRWBIF_PANELIDINFO_EX;
```


Java:  
public static class RWBIF_PANELIDINFO_EX extends Structure {

   	public byte[] szBarcode = new byte[68];

   	public int nLane;

   	@Override
   	protected List<String> getFieldOrder() {
   		// TODO Auto-generated method stub
   		return Arrays.asList(new String[] { "szBarcode", "nLane" });
   	}

   }
   
   [注]:fileOrder 必须按顺序填写

调用结构体结构体指针或结构体引用,要实现Structure.ByReference
直接传值 要实现Structure.ByValue

C++

typedef struct _tag_RWBIF_AUTO_JOB_CHG_RESULT
{
	TCHAR szMcName[32];
	DWORD dwErrorCode;
} RWBIF_AUTO_JOB_CHG_RESULT, *PRWBIF_AUTO_JOB_CHG_RESULT;


java 实现
public static class RWBIF_AUTO_JOB_CHG_RESULT extends Structure {

		public static class ByReference extends RWBIF_AUTO_JOB_CHG_RESULT implements Structure.ByReference {
		}

		public static class ByValue extends RWBIF_AUTO_JOB_CHG_RESULT implements Structure.ByValue {
		}

		public byte[] szMcName = new byte[32];

		public int dwErrorCode;

		@Override
		protected List<String> getFieldOrder() {
			// TODO Auto-generated method stub
			return Arrays.asList(new String[] { "szMcName", "dwErrorCode" });
		}
	}

复杂结构体,其成员函数包括结构体的指针或引用

C++

typedef struct _tag_RWBIF_HELPS_CHGOVERJOB
{
	INT nLane;
	RWBIF_JOBINFO_EX stJob;
} RWBIF_HELPS_CHGOVERJOB, *PRWBIF_HELPS_CHGOVERJOB;
其中 RWBIF_JOBINFO_EX 为另一个结构体,此处直接传值

java定义
public static class PRWBIF_HELPS_CHGOVERJOB extends Structure {

		public static class ByReference extends PRWBIF_HELPS_CHGOVERJOB implements Structure.ByReference {
		}
		public static class ByValue extends PRWBIF_HELPS_CHGOVERJOB implements Structure.ByValue {
		}
		public int nLane;

		public RWBIF_JOBINFO_EX stJob;

		@Override
		protected List<String> getFieldOrder() {
			// TODO Auto-generated method stub
			return Arrays.asList(new String[] { "nLane", "stJob" });
		}

	}

  • 指针类型使用
    int型指针
    IntByReference

  • 3. 函数映射
    结构体指针映射,可以用结构体数组代替
    java中声明的接口必须与DLL一样,包括 返回值、函数名。类型映射以及参数名称都要一样

C++

typedef INT (*pChangeOverJob)(LPCTSTR szSrv, LPCTSTR szLine, LPCTSTR szEquip, INT nJobChgMode, INT nQty, INT nSize, PRWBIF_HELPS_CHGOVERJOB pArg);
此处 PRWBIF_HELPS_CHGOVERJOB  为结构体指针,在java映射中可以用结构体数组代替
java
int iChangeOverJob(String szSrv, String szLine, String szEquip, int nJobChgMode, int nQty, int nSize,
			PRWBIF_HELPS_CHGOVERJOB[] pArg);
				PRWBIF_HELPS_CHGOVERJOB[] pArg 为对应的入参

复杂参数:指针的引用,JNA参数替换

C++

typedef INT (*pGetAutoJobChgResult)(PRWBIF_AUTO_JOB_CHG_RESULT &rval);
其中 PRWBIF_AUTO_JOB_CHG_RESULT 为结构体指针,此处要用byReference[]数组代替
int iGetAutoJobChgResult(RWBIF_AUTO_JOB_CHG_RESULT.ByReference[] rval);


  • 参考示例
JNA示例:C++类型映射
public interface NxtService extends Library {



	/** The default nxt dll name. */
	public static String DEFAULT_NXT_DLL_NAME = "RWBIF";

	/**
	 * The Class _tag_RWBIF_PANELIDINFO_EX.
	 */
	public static class RWBIF_PANELIDINFO_EX extends Structure {

		public byte[] szBarcode = new byte[68];

		public int nLane;

		@Override
		protected List<String> getFieldOrder() {
			// TODO Auto-generated method stub
			return Arrays.asList(new String[] { "szBarcode", "nLane" });
		}

	}

	public static class RWBIF_AUTO_JOB_CHG_RESULT extends Structure {

		public static class ByReference extends RWBIF_AUTO_JOB_CHG_RESULT implements Structure.ByReference {
		}

		public static class ByValue extends RWBIF_AUTO_JOB_CHG_RESULT implements Structure.ByValue {
		}

		public byte[] szMcName = new byte[32];

		public int dwErrorCode;

		@Override
		protected List<String> getFieldOrder() {
			// TODO Auto-generated method stub
			return Arrays.asList(new String[] { "szMcName", "dwErrorCode" });
		}
	}

	public static class RWBIF_JOBINFO_EX extends Structure {

		public static class ByReference extends RWBIF_JOBINFO_EX implements Structure.ByReference {
		}
		public static class ByValue extends RWBIF_JOBINFO_EX implements Structure.ByValue {
		}
		public byte[] szJobName = new byte[128];

		public byte[] szRevision = new byte[16];

		public int nSide;

		@Override
		protected List<String> getFieldOrder() {
			// TODO Auto-generated method stub
			return Arrays.asList(new String[] { "szJobName", "szRevision", "nSide" });
		}

	}

	public static class PRWBIF_HELPS_CHGOVERJOB extends Structure {

		public static class ByReference extends PRWBIF_HELPS_CHGOVERJOB implements Structure.ByReference {
		}
		public static class ByValue extends PRWBIF_HELPS_CHGOVERJOB implements Structure.ByValue {
		}
		public int nLane;

		public RWBIF_JOBINFO_EX stJob;

		@Override
		protected List<String> getFieldOrder() {
			// TODO Auto-generated method stub
			return Arrays.asList(new String[] { "nLane", "stJob" });
		}

	}

	
	int iSendBarcodeIdEx(String szSrv, String szLine, String szEquip, int nJobChgMode, int nQty, int nSize,
			RWBIF_PANELIDINFO_EX[] pArg);

	int iGetRecipeChgProgress(String szSrv, String szLine, String szEquip, IntByReference rdwStatus);

	int iGetAutoJobChgEquipQty(IntByReference rnQty, String szSrv, String szLine, String szEquip);

	void iDelGetAutoJobChgResult();

	
	int iGetAutoJobChgResult(RWBIF_AUTO_JOB_CHG_RESULT.ByReference[] rval);

	int iChangeOverJob(String szSrv, String szLine, String szEquip, int nJobChgMode, int nQty, int nSize,
			PRWBIF_HELPS_CHGOVERJOB[] pArg);

	

}

JNA测试:
public class NxtManager {

	public static String DEFAULT_NXT_PROPERTIES = "nxt.properties";

	private static String programName;

	private static String m_strRWBSeverPC;

	private static String m_strLine;

	private static String m_strEquip;

	private static String barcodeID;

	private static String lane;

	private static String szJobName;

	private static String version;

	private static String nSide;

	private static String encode;

	static {
		InputStream inputStream = Thread.currentThread().getContextClassLoader()
				.getResourceAsStream(DEFAULT_NXT_PROPERTIES);
		Properties properties = new Properties();
		try {
			properties.load(inputStream);
			programName = properties.getProperty("programName");
			m_strRWBSeverPC = properties.getProperty("server");
			m_strLine = properties.getProperty("lineName");
			m_strEquip = properties.getProperty("equipName");
			barcodeID = properties.getProperty("barcodeId");
			lane = properties.getProperty("lane");
			szJobName = properties.getProperty("jobName");
			version = properties.getProperty("revision");
			nSide = properties.getProperty("side");
			encode = properties.getProperty("encode");
			System.setProperty("jna.encoding", encode);

		} catch (IOException e) {
			// TODO Auto-generated catch block
			System.out.format("load nxt properties failed.");
			e.printStackTrace();
		}

	}

	public void onChangeoverJob() {
		NxtService nxtServiceInstance = (NxtService) Native.loadLibrary(NxtManager.programName, NxtService.class);
		int nDataQty = 1;
		int nIndex = 1;
		System.out.println("init---------->set value:");

		System.out.println("nLane:" + Integer.valueOf(NxtManager.lane));
		System.out.println("szJobName:" + NxtManager.szJobName);
		System.out.println("szRevision:" + NxtManager.version);
		System.out.println("nSide:" + Integer.valueOf(NxtManager.nSide));
		
		PRWBIF_HELPS_CHGOVERJOB[] prwbifHelpsChangeoverJob = (PRWBIF_HELPS_CHGOVERJOB[]) new NxtService.PRWBIF_HELPS_CHGOVERJOB()
				.toArray(nDataQty);
		prwbifHelpsChangeoverJob[0].nLane = Integer.valueOf(NxtManager.lane);
		
		RWBIF_JOBINFO_EX.ByValue stJobRef = new RWBIF_JOBINFO_EX.ByValue();

		
		stJobRef.nSide = Integer.valueOf(NxtManager.nSide);
		//不能声明直接进行赋值,java 会截断数组长度
		System.arraycopy(NxtManager.szJobName.getBytes(), 0, stJobRef.szJobName, 0, NxtManager.szJobName.getBytes().length);
		System.arraycopy(NxtManager.version.getBytes(), 0, stJobRef.szRevision, 0, NxtManager.version.getBytes().length);
		prwbifHelpsChangeoverJob[0].stJob = stJobRef;
	
		System.out.println("init---------->set value:end");

		int nJobChgMode = 1;
		int nSize = 152;

		System.out.println("iChangeOverJob---------->start");
		int nRet = nxtServiceInstance.iChangeOverJob(NxtManager.m_strRWBSeverPC, NxtManager.m_strLine,
				NxtManager.m_strEquip, nJobChgMode, nDataQty, nSize, prwbifHelpsChangeoverJob);
		if (0 != nRet) {
			System.out.format("API call [iChangeOverJob]: Error Code = %08x )", nRet);
			return;
		}
		System.out.println("iChangeOverJob---------->end");

		try {
			System.out.format("睡眠7s");
			Thread.sleep(TimeUnit.SECONDS.toMillis(7));
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return;
		}

		while (true) {
			IntByReference dwStatus = new IntByReference(0);
			System.out.println("iGetRecipeChgProgress---------->LOOP");
			nRet = nxtServiceInstance.iGetRecipeChgProgress(NxtManager.m_strRWBSeverPC, NxtManager.m_strLine,
					NxtManager.m_strEquip, dwStatus);
			if (0 != nRet) {
				System.out.format("API call [iGetRecipeChgProgress]: Error Code = %08x )", nRet);
				return;
			}
			int dwStatusValue = dwStatus.getValue();
			if (2 == dwStatusValue) {
				break;
			}
			try {
				System.out.format("睡眠7s钟,等待状态为complete(2)");
				Thread.sleep(TimeUnit.SECONDS.toMillis(7));
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return;
			}

		}
		System.out.println("iGetRecipeChgProgress---------->end,LOOP");

		IntByReference rnQty = new IntByReference(0);

		System.out.println("iGetAutoJobChgEquipQty---------->start");
		nRet = nxtServiceInstance.iGetAutoJobChgEquipQty(rnQty, NxtManager.m_strRWBSeverPC, NxtManager.m_strLine,
				NxtManager.m_strEquip);

		if (0 != nRet) {
			nxtServiceInstance.iDelGetAutoJobChgResult();
		}
		System.out.println("iGetAutoJobChgEquipQty---------->end");

		int rnQtyValue = rnQty.getValue();
		if (0 >= rnQtyValue) {
			nxtServiceInstance.iDelGetAutoJobChgResult();
			System.out.format("Error : Change over Result.(1)");
			return;
		}
		RWBIF_AUTO_JOB_CHG_RESULT.ByReference[] pResult =  (ByReference[]) new NxtService.RWBIF_AUTO_JOB_CHG_RESULT.ByReference()
				.toArray(rnQtyValue);

		System.out.println("iGetAutoJobChgResult---------->start");
		nRet = nxtServiceInstance.iGetAutoJobChgResult(pResult);
		if (0 != nRet) {
			nxtServiceInstance.iDelGetAutoJobChgResult();
			System.out.format("API call [iGetAutoJobChgEquipQty]: Error Code = %08x )", nRet);
			return;
		}
		System.out.println("iGetAutoJobChgResult---------->end");

		boolean bResultOK = false;
		for (int i = 0; i < rnQtyValue; i++) {

			System.out.println("iDelGetAutoJobChgResult---------->Loop");
			String szMcNameStr = new String(pResult[i].szMcName);
			if (NxtManager.m_strEquip.trim().equals(szMcNameStr.trim())) {
				if (0 != pResult[i].dwErrorCode) {
					nxtServiceInstance.iDelGetAutoJobChgResult();
					System.out.format("Error Code = %08x" + pResult[i].dwErrorCode);
					return;
				}
				bResultOK = true;
				break;
			}

		}
		System.out.println("iDelGetAutoJobChgResult---------->Loop end");
		if (false == bResultOK) {
			nxtServiceInstance.iDelGetAutoJobChgResult();
			System.out.format("Error : Change over Result.(2)");
			return;
		}
		nxtServiceInstance.iDelGetAutoJobChgResult();
		System.out.format("Change over from job complete.");
		return;
	}

	/*
	 * public static void main(String[] args) { NxtManager nxtManager = new
	 * NxtManager(); nxtManager.onChangeoverJob(); }
	 */

	public void OnChangeoverId() throws UnsupportedEncodingException  {
		System.out.println(System.getProperty("jna.encoding"));
		NxtService nxtServiceInstance = (NxtService) Native.loadLibrary(NxtManager.programName, NxtService.class);
		// String m_strRWBSeverPC = "10.187.0.54";
		// String m_strLine = "H12";
		// String m_strEquip = "NXT-H12";
		int nJobChgMode = 1;
		int nIndex = 1;

		int nDataQty = 1;
		int nSize = 140;
		// set lane and barcode id
		RWBIF_PANELIDINFO_EX[] pArg = (RWBIF_PANELIDINFO_EX[]) new NxtService.RWBIF_PANELIDINFO_EX().toArray(1);
		pArg[0].szBarcode = NxtManager.barcodeID.getBytes();
		pArg[0].nLane = Integer.valueOf(NxtManager.lane);

		System.out.println("SendBarcodeId---------->start");

		int nRet = nxtServiceInstance.iSendBarcodeIdEx(NxtManager.m_strRWBSeverPC, NxtManager.m_strLine,
				NxtManager.m_strEquip, nJobChgMode, nDataQty, nSize, pArg);
		if (0 != nRet) {
			System.out.format("API call [iSendBarcodeIdEx]: Error Code = %08x )", nRet);
			return;
		}
		System.out.println("SendBarcodeId---------->success");
		try {
			System.out.format("睡眠7s钟,等待状态为complete(2)");
			Thread.sleep(TimeUnit.SECONDS.toMillis(7));
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return;
		}
		while (true) {
			IntByReference dwStatus = new IntByReference(0);
			System.out.println("GetRecipeChgProgress---------->Loop");
			nRet = nxtServiceInstance.iGetRecipeChgProgress(NxtManager.m_strRWBSeverPC, NxtManager.m_strLine,
					NxtManager.m_strEquip, dwStatus);
			if (0 != nRet) {
				System.out.format("API call [iGetRecipeChgProgress]: Error Code = %08x )", nRet);
				return;
			}
			int dwStatusValue = dwStatus.getValue();
			if (2 == dwStatusValue) {
				break;
			}
			try {
				System.out.format("睡眠7s钟,等待状态为complete(2)");
				Thread.sleep(TimeUnit.SECONDS.toMillis(7));
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return;
			}

		}
		System.out.println("GetRecipeChgProgress---------->loop end");
		IntByReference rnQty = new IntByReference(0);

		System.out.println("GetAutoJobChgEquipQty---------->start");
		nRet = nxtServiceInstance.iGetAutoJobChgEquipQty(rnQty, NxtManager.m_strRWBSeverPC, NxtManager.m_strLine,
				NxtManager.m_strEquip);
		if (0 != nRet) {
			System.out.format("API call [iGetAutoJobChgEquipQty]: Error Code = %08x )", nRet);
			return;
		}

		System.out.println("GetAutoJobChgEquipQty---------->end");
		// RWBIF_AUTO_JOB_CHG_RESULT rval = new
		// NxtService.RWBIF_AUTO_JOB_CHG_RESULT();
		int size = rnQty.getValue();
		System.out.println("------------DEBUG------------->size" + size);
		if (0 >= size) {
			nxtServiceInstance.iDelGetAutoJobChgResult();
			System.out.format("Error : Change over Result.(1)");
			return;
		}
		
//		RWBIF_AUTO_JOB_CHG_RESULT.ByValue[] rval = (ByValue[]) new NxtService.RWBIF_AUTO_JOB_CHG_RESULT.ByValue().toArray(size);
		RWBIF_AUTO_JOB_CHG_RESULT.ByReference[] rval = (ByReference[]) new NxtService.RWBIF_AUTO_JOB_CHG_RESULT.ByReference().toArray(size);
		System.out.println("GetAutoJobChgResult---------->start");
//		nRet = nxtServiceInstance.iGetAutoJobChgResult(rval);
		nRet = nxtServiceInstance.iGetAutoJobChgResult(rval);
		if (0 != nRet) {
			System.out.format("API call [iGetAutoJobChgResult]: Error Code = %08x )", nRet);
			return;
		}
		System.out.println("GetAutoJobChgResult---------->end");
		boolean bResultOK = false;
		for (int i = 0; i < size; i++) {
			System.out.println("debug:current system encode:" + StringUtils.getEncoding(NxtManager.m_strEquip));
			String szMcNameStr = new String(rval[i].szMcName,StringUtils.getEncoding(NxtManager.m_strEquip));
			System.out.println("debug:szMcNameStr ----->" + szMcNameStr + ":" + szMcNameStr.length());
			System.out.println("debug:m_strEquip ----->" + NxtManager.m_strEquip  + ":" + NxtManager.m_strEquip.length());
			String tempStrEquip = new String(NxtManager.m_strEquip.getBytes(),StringUtils.getEncoding(NxtManager.m_strEquip));
			if (NxtManager.m_strEquip.equals(tempStrEquip)) {
				if (rval[i].dwErrorCode != 0) {
					nxtServiceInstance.iDelGetAutoJobChgResult();
					System.out.format("Error Code = %08x", rval[i].dwErrorCode);
					return;
				}
				bResultOK = true;
				System.out.println("debug:String equal:ok");
				break;
			}
		}
		if (false == bResultOK) {
			nxtServiceInstance.iDelGetAutoJobChgResult();
			System.out.format("Error : Change over Result.(2)");
			return;
		}
		System.out.println("success");
		nxtServiceInstance.iDelGetAutoJobChgResult();
		System.out.format("Change over from barcode ID complete.");
	}

	public static void main(String[] args) {

		if (args.length < 1 || args.length > 2) {
			System.out.println("参数不能为空");
			return;
		}
		boolean isExit = false;
		try {
			int model = Integer.valueOf(args[0]);
			NxtManager nxtManager = new NxtManager();
			switch (model) {
			case 0:
				System.out.println("OnChangeoverId:根据barcodeId自动换线");
				nxtManager.OnChangeoverId();
				break;
			case 1:
				System.out.println("onChangeoverJob:根据jobName自动换线");
				nxtManager.onChangeoverJob();
				break;
			default:
				System.out.println("不支持其它命令");
				break;
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			System.out.println("输入参数解析异常");
			e.printStackTrace();
		}
	}

}

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页