java调用ctp

1. 利用SWIG将CTP封装成JAVA版本

1.1 参考文章

利用SWIG将CTP封装成JAVA版本
CTP JAVA API(JCTP)编译(利用Swig封装C++动态库)windows版

1.2 环境准备

所有软件都采用最新版本,除vs需要安装,其它只需要解压,jdk、maven和eclipse的配置参考第一章 Java21开发环境配置
swigswig-4.1.1.tar.gz,解压到D:\java\swigwin-4.1.1
ctpCTP v6.7.2,解压到任意目录,找到目录20230913_traderapi64_se_windows
vsVisual Studio 2022 Community,直接安装

1.3 创建JAVA工程

在eclipse里创建一个maven工程:try-ctp
20230913_traderapi64_se_windows复制到try-ctp

20230913_traderapi64_se_windows新建文件thostapi.i

%module(directors="1") thostapi
%include "various.i"
%apply char **STRING_ARRAY { char *ppInstrumentID[] }

%{
#include "ThostFtdcMdApi.h"
#include "ThostFtdcTraderApi.h"
#include <codecvt>
#include <locale>
#include <vector>
#include <string>
using namespace std;
#ifdef _MSC_VER
const static locale g_loc("zh-CN");
#else   
const static locale g_loc("zh_CN.GB18030");
#endif
%}

%typemap(out) char[ANY], char[] {
    const std::string &gb2312($1);
    std::vector<wchar_t> wstr(gb2312.size());
    wchar_t* wstrEnd = nullptr;
    const char* gbEnd = nullptr;
    mbstate_t state = {};
    int res = use_facet<codecvt<wchar_t, char, mbstate_t> >
        (g_loc).in(state,
            gb2312.data(), gb2312.data() + gb2312.size(), gbEnd,
            wstr.data(), wstr.data() + wstr.size(), wstrEnd);
    if (codecvt_base::ok == res) {
        wstring_convert<codecvt_utf8<wchar_t>> cutf8;
        std::string result = cutf8.to_bytes(wstring(wstr.data(), wstrEnd));
        $result=JCALL1(NewStringUTF,jenv,result.c_str());
    } else {
        std::string result;
        $result=JCALL1(NewStringUTF,jenv,result.c_str());
    }
}
 
%feature("director") CThostFtdcMdSpi;
%ignore THOST_FTDC_VTC_BankBankToFuture;
%ignore THOST_FTDC_VTC_BankFutureToBank;
%ignore THOST_FTDC_VTC_FutureBankToFuture;
%ignore THOST_FTDC_VTC_FutureFutureToBank;
%ignore THOST_FTDC_FTC_BankLaunchBankToBroker;
%ignore THOST_FTDC_FTC_BrokerLaunchBankToBroker;
%ignore THOST_FTDC_FTC_BankLaunchBrokerToBank;
%ignore THOST_FTDC_FTC_BrokerLaunchBrokerToBank;
%include "ThostFtdcUserApiDataType.h"
%include "ThostFtdcUserApiStruct.h"
%include "ThostFtdcMdApi.h"
%feature("director") CThostFtdcTraderSpi;
%include "ThostFtdcTraderApi.h"

D:\java\swigwin-4.1.1\Lib\java复制various.i20230913_traderapi64_se_windows

E:\eclipse-workspace\tryto\try-ctp\20230913_traderapi64_se_windows文件清单如下:

error.dtd
error.xml
thostapi.i
ThostFtdcMdApi.h
ThostFtdcTraderApi.h
ThostFtdcUserApiDataType.h
ThostFtdcUserApiStruct.h
thostmduserapi_se.dll
thostmduserapi_se.lib
thosttraderapi_se.dll
thosttraderapi_se.lib
various.i

1.4 用swig生成代码

在命令行运行swig在20230913_traderapi64_se_windows生成thostapi_wrap.cppthostapi_wrap.h,同时在E:\eclipse-workspace\tryto\try-ctp\src\main\java\fun\tryto\ctp生成大量java文件

PS E:\eclipse-workspace\tryto\try-ctp\20230913_traderapi64_se_windows> D:\java\swigwin-4.1.1\swig.exe -c++ -java -package fun.tryto.ctp -outdir E:\eclipse-workspace\tryto\try-ctp\src\main\java\fun\tryto\ctp -o thostapi_wrap.cpp thostapi.i
ThostFtdcMdApi.h(30) : Warning 514: Director base class CThostFtdcMdSpi has no virtual destructor.
ThostFtdcTraderApi.h(30) : Warning 514: Director base class CThostFtdcTraderSpi has no virtual destructor.
PS E:\eclipse-workspace\tryto\try-ctp\20230913_traderapi64_se_windows>   

1.5 用vs创建java可以调用的dll动态库

打开Visual Studio 2022,创建新项目

选择“控制台应用”,下一步,项目名称:thostapi_wrap,位置:E:\eclipse-workspace\tryto\try-ctp\,勾选将解决方案和项目放在同一目录中,点击“创建”

创建项目后,在项目上右键-属性,“常规-配置类型”,选择dll,“C/C+±代码生成-运行库”,选择多线程(/MT)

完成之后,将E:\eclipse-workspace\tryto\try-ctp\20230913_traderapi64_se_windows里的文件拷贝到thostapi_wrap文件夹下,清单如下:

thostapi_wrap.cpp
thostapi_wrap.h
ThostFtdcMdApi.h
ThostFtdcTraderApi.h
ThostFtdcUserApiDataType.h
ThostFtdcUserApiStruct.h
thostmduserapi_se.lib
thosttraderapi_se.lib

右键头文件,添加现有项,添加5个h文件
右键资源文件,添加现有项,添加两个lib文件

工具栏,选择release x64,ctrl+F5,生成的代码位于E:\eclipse-workspace\tryto\try-ctp\thostapi_wrap\x64\Release

生成开始于 16:36...
1>------ 已启动生成: 项目: thostapi_wrap, 配置: Release x64 ------
1>thostapi_wrap.cpp
1>  正在创建库 E:\eclipse-workspace\tryto\try-ctp\thostapi_wrap\x64\Release\thostapi_wrap.lib 和对象 E:\eclipse-workspace\tryto\try-ctp\thostapi_wrap\x64\Release\thostapi_wrap.exp
1>正在生成代码
1>0 of 13441 functions ( 0.0%) were compiled, the rest were copied from previous compilation.
1>  0 functions were new in current compilation
1>  0 functions had inline decision re-evaluated but remain unchanged
1>已完成代码的生成
1>thostapi_wrap.vcxproj -> E:\eclipse-workspace\tryto\try-ctp\thostapi_wrap\x64\Release\thostapi_wrap.dll
========== 生成: 1 成功,0 失败,0 最新,0 已跳过 ==========
========== 生成 于 16:36 完成,耗时 05.836==========

复制thostapi_wrap.dll到E:\eclipse-workspace\tryto\try-ctp\lib
从E:\eclipse-workspace\tryto\try-ctp\20230913_traderapi64_se_windows复制两个dll到E:\eclipse-workspace\tryto\try-ctp\lib

至此所有文件生成完毕。

2. 在java工程里编写测试案例

案例是用的是sinow模拟账户,运行TestAPI需要配置vm参数:-Djava.library.path=E:\eclipse-workspace\tryto\try-ctp\lib
直接运行会报错UnsatisfiedLinkError

public class TestAPI {
	static {
		System.loadLibrary("thostmduserapi_se");
		System.loadLibrary("thosttraderapi_se");
		System.loadLibrary("thostapi_wrap");
	}

	public static void main(String[] args) {
		CThostFtdcTraderApi api = CThostFtdcTraderApi.CreateFtdcTraderApi();
		TraderSpiImpl spi = new TraderSpiImpl(api);
		api.RegisterSpi(spi);
		api.RegisterFront("tcp://180.168.146.187:10130");
		api.SubscribePublicTopic(THOST_TE_RESUME_TYPE.THOST_TERT_RESTART);
		api.SubscribePrivateTopic(THOST_TE_RESUME_TYPE.THOST_TERT_RESTART);
		api.Init();
		api.Join();
		api.Release();
		return;
	}
}



public class TraderSpiImpl extends CThostFtdcTraderSpi {
	final static String m_BrokerId = "9999";
	final static String m_UserId = "xxxxxxxxxxx";//手机号
	final static String m_InvestorId = "xxxxxx";
	final static String m_AccountId = "xxxxxxxxxxx";//手机号
	final static String m_appID = "simnow_client_test";
	final static String m_appCode = "0000000000000000";
	final static String m_PassWord = "xxxxxxxx";
	private List<String> ListExchanges = new ArrayList<String>();
	private List<String> ListProducts = new ArrayList<String>();
	private List<String> ListInstruments = new ArrayList<String>();

	TraderSpiImpl(CThostFtdcTraderApi traderapi) {
		m_traderapi = traderapi;
	}

	@Override
	public void OnFrontConnected() {
		Console.log("OnFrontConnected");
		CThostFtdcReqAuthenticateField clientAuth = new CThostFtdcReqAuthenticateField();
		clientAuth.setBrokerID(m_BrokerId);
		clientAuth.setUserID(m_UserId);
		clientAuth.setAppID(m_appID);
		clientAuth.setAuthCode(m_appCode);
		clientAuth.setUserProductInfo(m_appID);
		int b = m_traderapi.ReqAuthenticate(clientAuth, 0);
		Console.log("b:" + b);
		Console.log("Send auth ok");
	}

	@Override
	public void OnRspAuthenticate(CThostFtdcRspAuthenticateField field, CThostFtdcRspInfoField pRspInfo, int nRequestID, boolean bIsLast) {
		Console.log("OnRspAuthenticate:{}:{}:{}", bIsLast, JSONUtil.toJsonStr(field), JSONUtil.toJsonStr(pRspInfo));
		if (pRspInfo != null && pRspInfo.getErrorID() != 0) {
			System.out.printf("Auth ErrorID[%d] ErrMsg[%s]\n", pRspInfo.getErrorID(), pRspInfo.getErrorMsg());
			return;
		}
		Console.log("Auth success!!!");
		CThostFtdcReqUserLoginField userLogin = new CThostFtdcReqUserLoginField();
		userLogin.setBrokerID(m_BrokerId);
		userLogin.setUserID(m_InvestorId);
		userLogin.setPassword(m_PassWord);
		userLogin.setUserProductInfo("JAVA_API");
		int a = m_traderapi.ReqUserLogin(userLogin, 1);
		Console.log("a:" + a);
		Console.log("Send login ok");
	}

	@Override
	public void OnRspUserLogin(CThostFtdcRspUserLoginField pRspUserLogin, CThostFtdcRspInfoField pRspInfo, int nRequestID, boolean bIsLast) {
		Console.log("OnRspUserLogin:{}:{}:{}", bIsLast, JSONUtil.toJsonStr(pRspUserLogin), JSONUtil.toJsonStr(pRspInfo));
		if (pRspInfo != null && pRspInfo.getErrorID() != 0) {
			System.out.printf("Login ErrorID[%d] ErrMsg[%s]\n", pRspInfo.getErrorID(), pRspInfo.getErrorMsg());
			return;
		}
		Console.log(pRspUserLogin);
		Console.log("Login success!!!");
		CThostFtdcQryExchangeField pQryExchange = new CThostFtdcQryExchangeField();
		int b = m_traderapi.ReqQryExchange(pQryExchange, 1);
		Console.log("b:" + b);
	}

	@Override
	public void OnRspQryExchange(CThostFtdcExchangeField exchange, CThostFtdcRspInfoField pRspInfo, int nRequestID, boolean bIsLast) {
		Console.log("OnRspQryExchange:{}:交易所代码={},交易所名称={}", bIsLast, exchange.getExchangeID(), exchange.getExchangeName());
		ListExchanges.add(exchange.toString());
		if (bIsLast) {
			try {
				Thread.sleep(5000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			CThostFtdcQryProductField pQryProduct = new CThostFtdcQryProductField();
			int c = m_traderapi.ReqQryProduct(pQryProduct, 2);
		}
	}

	@Override
	public void OnRspQryProduct(CThostFtdcProductField product, CThostFtdcRspInfoField pRspInfo, int nRequestID, boolean bIsLast) {
		Console.log("OnRspQryProduct:{}:产品名称={},产品代码={},交易所代码={}", bIsLast, product.getProductName(), product.getProductID(), product.getExchangeID());
		ListProducts.add(product.toString());
		if (bIsLast) {
			try {
				Thread.sleep(5000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			CThostFtdcQryInstrumentField pQryInstrument = new CThostFtdcQryInstrumentField();
			int d = m_traderapi.ReqQryInstrument(pQryInstrument, nRequestID);
			Console.log("d:" + d);
		}
	}

	@Override
	public void OnRspQryInstrument(CThostFtdcInstrumentField instrument, CThostFtdcRspInfoField pRspInfo, int nRequestID, boolean bIsLast) {
		Console.log("OnRspQryInstrument:{}:合约名称={},合约代码={},产品代码={}", bIsLast, instrument.getInstrumentName(), instrument.getInstrumentID(), instrument.getProductID());
		ListInstruments.add(instrument.toString());
	}

	private CThostFtdcTraderApi m_traderapi;
}
  • 25
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
JCTP 0.3.2 2013-2-27 增加:JCTPStructUtil工具类 修正:交易API部分函数出现空指针异常的问题 修正:行情API部分函数出现空指针异常的问题 变更:发布包中增加JCTP.jar *********************************************** JCTP 0.3.1 2013-2-26 修正:交易API部分函数出现空指针异常的问题 *********************************************** JCTP 0.3 2013-2-26 增加:完成对交易API的封装 增加:格式化结构体方法注释为javadoc格式(暂未转成中文) 增加:优化结构体属性的调用方式,增加getter/setter方法,隐藏bridj框架代码 修正:解决Bridj框架中一处与CTP接口的兼容问题 修正:解决回调方法中结构体的属性值为中文时出现乱码的问题 变更:移动util包到jctp路径下 变更:发布版本号格式更改,缩进1位 *********************************************** JCTP 0.0.2 2013-1-31 增加:JCTPLibraryUtil类,用于初始化CTP环境或卸载CTP环境 增加:JCTPMdApi类,将Bridj调用CTP的代码隐藏 增加:JCTPMdSpi类,将Bridj调用CTP的代码隐藏 增加:JCTPTraderApi类,将Bridj调用CTP的代码隐藏 增加:JCTPTraderSpi类,将Bridj调用CTP的代码隐藏 修正:Spi回调时报空指针,无法进入回调方法的问题 修正:无法调用带参数的CreateFtdc.....Api函数的问题 修正:只能在调试模式下进行回调的问题 变更:CTP动态链接库置入jar包 变更:将JCTP相关类独立出CTP调用

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码未央

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值