利用SWIG将CTP封装成JAVA版本
重点参考景色大佬文章:
CTP JAVA API(JCTP)编译(利用Swig封装C++动态库)windows版_景色正好的博客-CSDN博客
Swig转换C++接口中文乱码解决方案_景色正好的博客-CSDN博客
其中第二篇文章里,直接用文中给出的i修改方式会报错,原因在文章的评论区。
最后可用的 .i 文件全文如下:(将市场接口和行情接口打包到一个jar中)
%module(directors="1") CTP4Java %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"
various.i 在swig安装目录中找到(如: D:\swig\swigwin-4.0.2\Lib\java)
命令如下:
( swig命令生成 ctp4java_wrap.h 和 ctp4java_wrap.cpp jar 命令打包成 ctp4java.jar )
mkdir src mkdir -p com/tugeler/ctp4java/v6_6_1 swig.exe -c++ -java -package com.tugeler.ctp4java.v6_6_1 -outdir src -o ctp4java_wrap.cpp ctp4java.i cd .\src\ javac *.java cd .. mv src/*.class .\com\tugeler\ctp4java\v6_6_1 jar.exe cf ctp4java.jar com
项目结构:
JAVA项目中设置环境变量
-Djava.library.path=$ProjectFileDir$/lib
然后代码中加载库
static { System.loadLibrary("product/thostmduserapi_se"); System.loadLibrary("product/thosttraderapi_se"); System.loadLibrary("ctp4java_wrap"); }
调用简单示例:
public static void main(String[] args) { CThostFtdcTraderApi api = CThostFtdcTraderApi.CreateFtdcTraderApi(); TraderSpiImpl spi = new TraderSpiImpl(api); api.RegisterSpi(spi); api.RegisterFront("tcp://111.222.333.444:56789"); 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; }
其中 SPI 是自己写的继承 CThostFtdcTraderSpi 后复写API中对应方法的响应。
class TraderSpiImpl extends CThostFtdcTraderSpi { final static String m_BrokerId = "xxxxx"; final static String m_UserId = "xxxxx"; final static String m_InvestorId = "xxxxx"; final static String m_AccountId = "xxxxx"; final static String m_appID = "xxxxx"; final static String m_appCode = "xxxxx"; final static String m_PassWord = "xxxxx"; 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() { System.out.println("On Front Connected"); 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); System.out.println("b:" + b); System.out.println("Send auth ok"); } @Override public void OnRspAuthenticate(CThostFtdcRspAuthenticateField field, CThostFtdcRspInfoField pRspInfo, int nRequestID, boolean bIsLast) { if (pRspInfo != null && pRspInfo.getErrorID() != 0) { System.out.printf("Auth ErrorID[%d] ErrMsg[%s]\n", pRspInfo.getErrorID(), pRspInfo.getErrorMsg()); return; } System.out.println("Auth success!!!"); CThostFtdcReqUserLoginField userLogin = new CThostFtdcReqUserLoginField(); userLogin.setBrokerID(m_BrokerId); userLogin.setUserID(m_UserId); userLogin.setPassword(m_PassWord); userLogin.setUserProductInfo("JAVA_API"); int a = m_traderapi.ReqUserLogin(userLogin, 1); System.out.println("a:" + a); System.out.println("Send login ok"); } @Override public void OnRspUserLogin(CThostFtdcRspUserLoginField pRspUserLogin, CThostFtdcRspInfoField pRspInfo, int nRequestID, boolean bIsLast) { if (pRspInfo != null && pRspInfo.getErrorID() != 0) { System.out.printf("Login ErrorID[%d] ErrMsg[%s]\n", pRspInfo.getErrorID(), pRspInfo.getErrorMsg()); return; } System.out.println(pRspUserLogin); System.out.println("Login success!!!"); CThostFtdcQryExchangeField pQryExchange = new CThostFtdcQryExchangeField(); int b = m_traderapi.ReqQryExchange(pQryExchange, 1); System.out.println("b:" + b); } @Override public void OnRspQryExchange(CThostFtdcExchangeField pExchange, CThostFtdcRspInfoField pRspInfo, int nRequestID, boolean bIsLast) { System.out.println(bIsLast + " : " +JSON.toJSONString(pExchange)); ListExchanges.add(pExchange.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 pProduct, CThostFtdcRspInfoField pRspInfo, int nRequestID, boolean bIsLast) { System.out.println(bIsLast + " : " +JSON.toJSONString(pProduct)); ListProducts.add(pProduct.toString()); if(bIsLast) { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } CThostFtdcQryInstrumentField pQryInstrument = new CThostFtdcQryInstrumentField(); int d = m_traderapi.ReqQryInstrument(pQryInstrument, nRequestID); System.out.println("d:"+d); } } @Override public void OnRspQryInstrument(CThostFtdcInstrumentField pInstrument, CThostFtdcRspInfoField pRspInfo, int nRequestID, boolean bIsLast) { System.out.println(bIsLast + " : " +JSON.toJSONString(pInstrument)); ListInstruments.add(pInstrument.toString()); } private CThostFtdcTraderApi m_traderapi; }
作者:Lighting Cui
出处:http://tugeler.cnblogs.com/
本文版权归作者所,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
出处:http://tugeler.cnblogs.com/
本文版权归作者所,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。