利用SWIG将CTP封装成JAVA版本
重点参考景色大佬文章:
CTP JAVA API(JCTP)编译(利用Swig封装C++动态库)windows版_景色正好的博客-CSDN博客
Swig转换C++接口中文乱码解决方案_景色正好的博客-CSDN博客
其中第二篇文章里,直接用文中给出的i修改方式会报错,原因在文章的评论区。
最后可用的 .i 文件全文如下:(将市场接口和行情接口打包到一个jar中)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | %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 )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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项目中设置环境变量
1 | -Djava.library.path=$ProjectFileDir$/lib |
然后代码中加载库
1 2 3 4 5 | static { System.loadLibrary( "product/thostmduserapi_se" ); System.loadLibrary( "product/thosttraderapi_se" ); System.loadLibrary( "ctp4java_wrap" ); } |
调用简单示例:
1 2 3 4 5 6 7 8 9 10 11 12 | 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中对应方法的响应。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | 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/
本文版权归作者所,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理