通过JNA在Java中模拟联合体(Union)

在Java中调用动态链接库(.dll),不考虑性能的话用JNA比用JNI要方便多了,只需要做数据映射之后再将导出函数声明一下就行了。下面分享一下通过JNA在Java中模拟联合体(Union)的经验。

示例来源于某CAN接口卡的开发库:

typedef struct tagZCAN_CHANNEL_INIT_CONFIG {
     
	UINT can_type; // 0:can 1:canfd
	union
	{
     
		struct
		{
     
			UINT acc_code;
			UINT acc_mask;
			UINT reserved;
			BYTE filter;
			BYTE timing0;
			BYTE timing1;
			BYTE mode;
		}can;
		struct
		{
     
			UINT acc_code;
			UINT acc_mask;
			UINT abit_timing;
			UINT dbit_timing;
			UINT brp;
			BYTE filter;
			BYTE mode;
			USHORT pad;
			UINT reserved;
		}canfd;
	};
}ZCAN_CHANNEL_INIT_CONFIG;

根据JNA的帮助文档:

Unions are generally interchangeable with Structures, but require that you indicate which union field is active with the setType method before it can be properly passed to a function call.

我们在模拟联合体时需要用setType方法来指定激活哪一个字段。我个人的理解是由于Java中压根儿就没有共用内存这种做法,所以通过不同内存上的字段来模拟,进而需要先告诉程序我们要用哪段内存(哪一个字段)。

注意:帮助文档中没有提及重写read和write方法,但这是必不可少的,并且setType方法就应该写在这俩里面。

下面给出相应的Java示例代码以供参考:

@Structure.FieldOrder({
     "can_type", "cfg_union"})
public class ZCAN_CHANNEL_INIT_CONFIG extends Structure {
     
	public int can_type;
	public tagCfg_union cfg_union;
	public static class ByValue extends ZCAN_CHANNEL_INIT_CONFIG implements Structure.ByValue{
     }
	public static class ByReference extends ZCAN_CHANNEL_INIT_CONFIG implements Structure.ByReference{
     }

	public static class tagCfg_union extends Union {
     
		public tagCan can;
		public tagCanfd canfd;

		@Structure.FieldOrder({
     "acc_code", "acc_mask", "reserved", "filter", "timing0", "timing1", "mode"})
		public static class tagCan extends Structure {
     
			public int acc_code;
			public int acc_mask;
			public int reserved;
			public byte filter;
			public byte timing0;
			public byte timing1;
			public byte mode;
		}
		
		@Structure.FieldOrder({
     "acc_code", "acc_mask", "abit_timing", "dbit_timing", "brp", "filter", "mode", "pad", "reserved"})
		public static class tagCanfd extends Structure {
     
			public int acc_code;
			public int acc_mask;
			public int abit_timing;
			public int dbit_timing;
			public int brp;
			public byte filter;
			public byte mode;
			public short pad;
			public int reserved;
		}
	}

	@Override
	public void read() {
     
		super.read();
		switch(can_type) {
     
		case 0:
			cfg_union.setType(tagCan.class);
			break;
		case 1:
			cfg_union.setType(tagCanfd.class);
			break;
		}
		cfg_union.read();
	}

	@Override
	public void write() {
     
		super.write();
		switch(can_type) {
     
		case 0:
			cfg_union.setType(tagCan.class);
			break;
		case 1:
			cfg_union.setType(tagCanfd.class);
			break;
		}
		cfg_union.write();
	}
}

类命名不规范(有的首字母未大写),请忽略,hh

你可能感兴趣的:(Java语言相关学习记录,java,JNA实例,dll,Union)