JNA调用C语言dll

JNA调用C语言dll

最近公司要求要要用java
代码调用C语言的接口,给我一个dll文件去,看了网上一些,不太全,还是踩了很多坑,把踩得的坑记录下来,希望能帮助到你

首先新建一个maven项目,导入所需要的JNA包

<dependency> 
			<groupId>net.java.dev.jna</groupId> 
			<artifactId>jna</artifactId> 
			<version>4.1.0</version>
</dependency>

将dll文件放到jdk对应的bin目录下,或者是放到C:\Windows\System32
CLibrary INSTTANCE = (CLibrary) Native.loadLibrary("", CLibrary.class);
但是这样有点不好,我们想将文件放到项目里面,跟着项目一起,

public interface CLibrary extends Library {
		
		String path = Thread.currentThread().getContextClassLoader().getResource("").getPath().replaceAll("%20"," ").replaceFirst("/","").replace("/","\\")+"win32-x64\\JGDFDAPI";
		CLibrary INSTTANCE = (CLibrary) Native.loadLibrary(path, CLibrary.class);
}	

这样就能放到项目里边了
在这里插入图片描述
直接放导resources下面

这里有个坑,里边对应的dll文件必须与jdk的位数相对应,另外eclipse32位的不能调用64位的dll,即使jdk是64位的也不行,还有,dll内部引用的文件必须全部弄进来,否则也会是报找不到对应文件(这个问题困扰了我一天才解决,一直以为只要一个dll文件就可以了)

最基础的部分就到这里了,然后最最重要也是最麻烦的来了,数据类型,大家可以去看下C语言对应java的数据类型

这些基本能解决你的问题了,但是也会有特殊的,例如枚举,

JGDFDAPI int DFDAPI_SetEnv(DFDAPI_SET_ENVIRONMENT eSetEnv, int nEnvValue);

在这里插入图片描述
以上是C语言中的接口。以及枚举类

其实这里对应java中,你可以创建一个枚举或者是一个接口,参数看成是一个常量

public interface DFDAPI_SET_ENVIRONMENT {
	
	public static final int DFDAPI_ENVIRON_HEART_BEAT_INTERVAL=0;//("Heart Beat间隔(秒数),若值为0则表示默认值10秒钟"),
	
	public static final int DFDAPI_ENVIRON_OPEN_TIME_OUT=0;//(" 在调DFDAPI_Open期间,接收每一个数据包的超时时间(秒数,不是DFDAPI_Open调用总的最大等待时间),若值为0则默认30秒"),
	
	public static final int DFDAPI_ENVIRON_USE_PACK_OVER=1;//(""),
	
	public static final int DFDAPI_ENVIRON_HEART_BEAT_FLAG=1;//("心跳数据发送方式(0: 取消发送心跳包 1:没有数据发送的时候发送心跳数据,2:有规律发送心跳数据)"),
	
	public static final int DFDAPI_ENVIRON_SOURCE_MODE=1;//("双活数据源模式,值参考DFDAPI_SOURCE_SETTING枚举类"),	
	
	public static final int DFDAPI_ENVIRON_SOURCE_MODE_VALUE=1;//("双活数据源模式下参数的值"),
	
	public static final int DFDAPI_ENVIRON_OUT_LOG=1;//("当前目录下创建log,否则在当前路径有log文件夹时创建到log文件夹中"),		
	
	public static final int DFDAPI_ENVIRON_SNAPSHOT_ENENT=1;//("发送快照事件和清盘通知但快照不发送到回调函数,否则直接发送快照到回调函数,无快照通知"),	
	
	public static final int DFDAPI_ENVIRON_ORIGINAL_VOL=1;//("原始结构有效,1、指数成交量和成交额的单位为股和元,默认为100股和100元"),
	
	public static final int DFDAPI_ENVIRON_BREAKPOINT=1;//("1.网络断开后断点续传,else.请求最新快照"),
	
	public static final int DFDAPI_ENVIRON_PUSHMODE=1;//("0:启用默认订阅推送;1:禁用默认订阅推送。"),
	
	public static final int DFDAPI_ENVIRON_COMPRESS=1;//("0:默认压缩传输行情数据;1:不压缩传输行情数据。");
}

对应java方法

/*
		* 设置环境变量 一个变量类型设置一次,可以不设置使用默认值,默认值参考DFDAPI_SET_ENVIRONMENT
		* @param[in] eSetEnv 环境变量设置项
		* @param[in] unEnvValue 环境变量设置值
		* return 成功:DFDAPI_ERR_SUCCESS 未知参数:DFDAPI_ERR_INVALID_PARAMS
		*/
		public int DFDAPI_SetEnv(int eSetEnv, int nEnvValue);

C接口中传参为Struct,相当于java中对象
struct DFDAPI_OPEN_CONNECT_SET
{
DFDAPI_SERVER_INFO ServerInfo[JGAPI_SERVERINFO_MAX];
unsigned int unServerNum;
dfdapi_data_callback data_fun;
dfdapi_notice_callback notice_fun;
const char* szMarkets;
const char* szSubScriptions;
const char* szTypeFlags;
unsigned int nTime;
unsigned int nConnectionID;
};

/*
* 打开服务链接
* @param[in] pConnectSet 连接参数设置,在调用期间会通过回调收到连接登录获取代码表结果消息
* 如果断开连接会将错误码放入pErrCode
* @param[in] pErrCode 错误码
* return 成功返回一个实例标识 否则返回NULL
*/
JGDFDAPI VHANDLE DFDAPI_OpenConnect(DFDAPI_OPEN_CONNECT_SET *pConnectSet, DFDAPI_ERR_CODE *pErrCode);

public class DFDAPI_OPEN_CONNECT_SET extends Structure{
	
	public DFDAPI_SERVER_INFO [] serverInfos = (DFDAPI_SERVER_INFO[]) new DFDAPI_SERVER_INFO().toArray(100);				///< 服务器信息
	
	public int unServerNum;										///< 服务器数量
	
	public String szMarkets;									///< 市场订阅!例如"SZ;SH;CF;SHF;DCE;SHF",需要订阅的市场列表,以“;”分割.
	
	public String szSubScriptions;								///< 代码订阅!例如"600000.sh;IH1711.cf;000001.sz",需要订阅的股票,以“;”分割.
	
	public String szTypeFlags;									///< 数据类型订阅!支持订阅3种类型TRANSACTION;ORDER;ORDERQUEUE。!注意:行情数据任何时候都发送,不需要订阅! 参见enum DATA_TYPE_FLAG.
	
	public int nTime;											///< 为0则请求实时行情,为0xffffffff从头请求.
	
	public int nConnectionID;									///< 连接ID,连接回调消息的附加结构 DFDAPI_CONNECT_RESULT中 会包含这个ID,消息头也会包含该ID.
	
	public DFDAPI_OPEN_CONNECT_SET(String vHandle, DFDAPI_CALLBACK_MSG pMsg) {
		JavaCallC.CLibrary.ccback callback = new CallBackImpl();
		callback.dfdapi_data_callback(vHandle, pMsg);
		callback.dfdapi_notice_callback(vHandle, pMsg);
	}
	public DFDAPI_OPEN_CONNECT_SET() {

	}
	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	protected List getFieldOrder() {
		List list = new ArrayList();
		list.add("serverInfos");
		list.add("unServerNum");
		list.add("szMarkets");
		list.add("szSubScriptions");
		list.add("szTypeFlags");
		list.add("nTime");
		list.add("nConnectionID");
		return list;

	}


	public DFDAPI_SERVER_INFO[] getServerInfos() {
		return serverInfos;
	}

	public void setServerInfos(DFDAPI_SERVER_INFO[] serverInfos) {
		this.serverInfos = serverInfos;
	}

	public int getUnServerNum() {
		return unServerNum;
	}


	public void setUnServerNum(int unServerNum) {
		this.unServerNum = unServerNum;
	}


	public String getSzMarkets() {
		return szMarkets;
	}


	public void setSzMarkets(String szMarkets) {
		this.szMarkets = szMarkets;
	}


	public String getSzSubScriptions() {
		return szSubScriptions;
	}


	public void setSzSubScriptions(String szSubScriptions) {
		this.szSubScriptions = szSubScriptions;
	}


	public String getSzTypeFlags() {
		return szTypeFlags;
	}


	public void setSzTypeFlags(String szTypeFlags) {
		this.szTypeFlags = szTypeFlags;
	}


	public int getnTime() {
		return nTime;
	}


	public void setnTime(int nTime) {
		this.nTime = nTime;
	}


	public int getnConnectionID() {
		return nConnectionID;
	}


	public void setnConnectionID(int nConnectionID) {
		this.nConnectionID = nConnectionID;
	}	
	


}
public class DFDAPI_SERVER_INFO extends Structure{
	public byte [] szIp = new byte[32]; 
	
	public short nPort;
	
	public byte [] szUser = new byte[64];
	
	public byte [] szPwd = new byte[64];
	
	public int bDoMain;

	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	protected List getFieldOrder() {
		List list = new ArrayList();
		list.add("szIp");
		list.add("nPort");
		list.add("szUser");
		list.add("szPwd");
		list.add("bDoMain");
		return list;

	}

	public byte[] getSzIp() {
		return szIp;
	}

	public void setSzIp(byte[] szIp) {
		this.szIp = szIp;
	}

	public short getnPort() {
		return nPort;
	}

	public void setnPort(short nPort) {
		this.nPort = nPort;
	}

	public byte[] getSzUser() {
		return szUser;
	}

	public void setSzUser(byte[] szUser) {
		this.szUser = szUser;
	}

	public byte[] getSzPwd() {
		return szPwd;
	}

	public void setSzPwd(byte[] szPwd) {
		this.szPwd = szPwd;
	}

	public int getbDoMain() {
		return bDoMain;
	}

	public void setbDoMain(int bDoMain) {
		this.bDoMain = bDoMain;
	}
}

继承Struct类,重写getFieldOrder(),把对应的属性都填进去,
里面有几个坑,给大家说下,记得一定要初始化数组,不然会报数组没有初始化,
里面对应的属性也要设置成public,设置成private会报属性只能设置为public
char szIp [32],对应public byte [] szIp = new byte[32]; 也要初始化,位数对应c中的位数,不然一直报无效内存

好了,这是我第一次写jna,记录一下,希望能帮到你,写的不好的地方希望各位海涵

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值