CTP JAVA API(JCTP)编译(利用Swig封装C++动态库)windows版
来源:互联网 发布:淘宝给了差评还能改吗 编辑:程序博客网 时间:2024/06/05 12:03
前言:
目前上期技术CTP系统提供的API版本是C++
版本,而很多客户采用Java
开发,就产生了一些问题。SWIG
是一个能将C/C++
接口转换为其他语言的工具,目前可以支持Python,Java,R
等语言。
本文主要介绍Windows 32位平台下利用Swig工具将CTP C++接口API转换为Java可调用的接口。
1. 准备工作
从CTP官网上下载
CTP API
点击下载。32位的API文件包清单如下:error.dtd
error.xml
ThostFtdcMdApi.h
ThostFtdcTraderApi.h
ThostFtdcUserApiDataType.h
ThostFtdcUserApiStruct.h
thostmduserapi.dll
thostmduserapi.lib
thosttraderapi.dll
thosttraderapi.lib安装Swig软件,本文中所用的Swig是
swigwin-2.0.11
版本,点击下载。- 安装JDK,注意要安装32位版本,将环境变量配置好。本文所用的是
1.8.0_111
版本,点击下载 。 - 安装
liviconv
库。这个库主要适用于字节编码转换,因为CTP的结算单信息是GB2312编码,而Java采用UTF-8编码,如果不进行字节转换,得到的结算单信息中的中文将会是乱码。 本文采用的liviconv版本是libiconv-1.9.2-1
,点击下载 - 安装Eclipse,注意,也需要下载32位版本。主要用与Java demo的测试,点击下载
2. 通过Swig得到jar包
在刚刚下载得到的API文件夹20160606_tradeapi_windows
内,新建文件thosttraderapi.i
,内容如下
%module(directors=”1”) thosttradeapi
%{
#include “ThostFtdcTraderApi.h”
%}
%feature(“director”) CThostFtdcTraderSpi;
%include “ThostFtdcUserApiDataType.h”
%include “ThostFtdcUserApiStruct.h”
%include “ThostFtdcTraderApi.h”
这是一个接口文件,用于告诉swig为哪些类和方法创建接口。*.i文件的具体解释参考这篇文章《用Swig封装C/C++》。然后在当前目录内建立文件夹src
,wrap
和test
,在test
文件夹内建立文件夹thosttraderapi
。打开windows cmd
工具,cd
到当前目录\20160606_tradeapi_windows
下。 在cmd
中运行命令
swig.exe -c++ -java -package test.thosttraderapi -outdir src -o thosttraderapi_wrap.cpp thosttraderapi.i
等到运行完成后,可以看到当前目录下生成了
thosttraderapi_wrap.h
thosttraderapi_wrap.cpp
这两个文件是用于包装原来C++
接口的文件,下面要用。打开src
文件夹,可以看到这时在里面生成了一系列方法的java文件,如下:
CThostFtdcAccountregisterField.java
CThostFtdcAuthenticationInfoField.java
… … …
thosttradeapiJNI.java
在cmd
中cd
到src
文件夹底下,运行命令
javac *.java
运行结束之后可以看到生成了等量的class文件,将所有的class文件拷贝到\test\thosttraderapi\
文件夹中,cmd
下cd
到20160606_tradeapi_windows
目录下,运行命令
jar cf thosttraderapi.jar test
这样我们就在当前文件夹下得到了jar包thosttraderapi.jar
。
3. 通过C++得到java可调用的dll动态库
接下来在wrap
文件夹中,建立一个C++工程,工程的应用程序类型选DLL
,工程名为thosttraderapi_wrap
,将如下文件拷贝到\wrap\thosttraderapi_wrap\thosttraderapi_wrap
文件夹下:
ThostFtdcTraderApi.h
ThostFtdcUserApiDataType.h
ThostFtdcUserApiStruct.h
thosttraderapi.lib
thosttraderapi_wrap.cpp
thosttraderapi_wrap.h
在c++
工程中添加现有项,将这些文件全部添加到工程中去。下面还要做几步:
- 将你安装jdk目录
\Java\jdk1.8.0_111\include
下的jni.h
和win32
文件夹下的jni_md.h, jawt_md.h
一共三个文件拷贝到安装vs的include目录底下\Microsoft Visual Studio 12.0\VC\include
。这是因为thosttraderapi_wrap.cpp
文件中包含了<jni.h>
,这是用于生成Java
可调用接口的库文件。 - 将你安装的
libiconv
目录下文件夹\GnuWin32\include
中的iconv.h
文件同样拷贝到刚才的C++ include
目录\Microsoft Visual Studio 12.0\VC\include
下。将\GnuWin32\bin
文件夹下的libiconv2.dll
拷贝到20160606_tradeapi_windows
目录下备用。将\GnuWin32\lib
文件夹下的libiconv.lib
文件拷贝到C++
工程文件夹底下\wrap\thosttraderapi_wrap\thosttraderapi_wrap
,然后将这个lib
文件添加到工程中。这是用于字节转换的动态库。
这所有完成之后,C++
工程中文件应该如下:
接下来还需要对thosttraderapi_wrap.cpp
文件进行一些编辑:
- 因为结算单信息中有很多中文,CTP结算单是GB2312编码,Java输出是UTF-8编码,所以要进行字节转换。 在
thosttraderapi_wrap.cpp
文件开头添加如下代码(如果你不care结算单上的中文信息,这一步你可以不做):
#pragma warning(disable:4996)#include <iconv.h>int code_convert(const char *from_charset, const char *to_charset, char *inbuf, size_t inlen, char *outbuf, size_t outlen){ iconv_t cd; int rc; char **pin = &inbuf; char **pout = &outbuf; cd = iconv_open(to_charset, from_charset); int argument = 1; if (cd == 0) return -1; if (iconv(cd, (const char **)pin, &inlen, pout, &outlen) == -1) { iconv_close(cd); return -1; } iconv_close(cd); return 0;}#define GB2312TOUTF8FORCONTENT \ char result_utf8[1000]={0}; \ if(result) \ { \ unsigned int inlength=strlen(result); \ int rsp=code_convert("gb2312","utf-8",result,inlength,result_utf8,1000);\ if(rsp!=-1) jresult = jenv->NewStringUTF((const char *)result_utf8);\ }
搜索文件中Java_test_thosttraderapi_thosttradeapiJNI_CThostFtdcSettlementInfoField_1Content_1get
函数,将函数中
if (result) jresult = jenv->NewStringUTF((const char *)result);
语句替换为:
GB2312TOUTF8FORCONTENT
将如下8个函数注释掉,这几个函数中涉及到将字符串转换为
char
类型,有问题,也没什么用。Java_test_thosttraderapi_thosttradeapiJNI_THOST_1FTDC_1VTC_1BankBankToFuture_1get
Java_test_thosttraderapi_thosttradeapiJNI_THOST_1FTDC_1VTC_1BankFutureToBank_1get
Java_test_thosttraderapi_thosttradeapiJNI_THOST_1FTDC_1VTC_1FutureBankToFuture_1get
Java_test_thosttraderapi_thosttradeapiJNI_THOST_1FTDC_1VTC_1FutureFutureToBank_1get
Java_test_thosttraderapi_thosttradeapiJNI_THOST_1FTDC_1FTC_1BankLaunchBankToBroker_1get
Java_test_thosttraderapi_thosttradeapiJNI_THOST_1FTDC_1FTC_1BrokerLaunchBankToBroker_1get
Java_test_thosttraderapi_thosttradeapiJNI_THOST_1FTDC_1FTC_1BankLaunchBrokerToBank_1get
Java_test_thosttraderapi_thosttradeapiJNI_THOST_1FTDC_1FTC_1BrokerLaunchBrokerToBank_1get这样全部完成之后,我们按F7编译,在
\wrap\thosttraderapi_wrap\Debug
目录底下可见thosttraderapi_wrap.dll
动态库文件,说明编译成功,这样CTP Java API
就编译成功了。
4. Java Demo
打开Eclipse,新建traderapidemo
工程。
- 在工程中新建
lib
文件夹,将刚刚的thosttraderapi.jar
包拷贝到该文件夹底下,刷新工程,在工程中jar包上右击选择BuildPath/Add to Build Path
将jar包导入到工程。 - 将如下三个动态库文件
thosttraderapi.dll
thosttraderapi_wrap.dll
libiconv2.dll
拷贝到你电脑环境变量path
路径底下,如果自己不清楚,可以在Java
中用如下代码获得
System.out.println(System.getProperty("java.library.path"));
我直接拷贝到了\Java\jdk1.8.0_111
底下。
完整的demo代码如下:
package traderapidemo;import test.thosttraderapi.*;;class TraderSpiImpl extends CThostFtdcTraderSpi{ final static String m_BrokerId = "8000"; final static String m_UserId = "000326"; final static String m_InvestorId = "000326"; final static String m_PassWord = "password"; final static String m_TradingDay = "20161111"; final static String m_AccountId = "000326"; final static String m_CurrencyId = "CNY"; TraderSpiImpl(CThostFtdcTraderApi traderapi) { m_traderapi = traderapi; } @Override public void OnFrontConnected(){ System.out.println("On Front Connected"); CThostFtdcReqUserLoginField field = new CThostFtdcReqUserLoginField(); field.setBrokerID(m_BrokerId); field.setUserID(m_UserId); field.setPassword(m_PassWord); field.setUserProductInfo("JAVA_API"); m_traderapi.ReqUserLogin(field,0); 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("Login success!!!"); CThostFtdcQryTradingAccountField qryTradingAccount = new CThostFtdcQryTradingAccountField(); qryTradingAccount.setBrokerID(m_BrokerId); qryTradingAccount.setCurrencyID(m_CurrencyId);; qryTradingAccount.setInvestorID(m_InvestorId); m_traderapi.ReqQryTradingAccount(qryTradingAccount, 1); } @Override public void OnRspQryTradingAccount(CThostFtdcTradingAccountField pTradingAccount, CThostFtdcRspInfoField pRspInfo, int nRequestID, boolean bIsLast) { if (pRspInfo != null && pRspInfo.getErrorID() != 0) { System.out.printf("OnRspQryTradingAccount ErrorID[%d] ErrMsg[%s]\n", pRspInfo.getErrorID(), pRspInfo.getErrorMsg()); return; } if (pTradingAccount != null) { System.out.printf("Balance[%f]Available[%f]WithdrawQuota[%f]Credit[%f]\n", pTradingAccount.getBalance(), pTradingAccount.getAvailable(), pTradingAccount.getWithdrawQuota(), pTradingAccount.getCredit()); } else { System.out.printf("NULL obj\n"); } } private CThostFtdcTraderApi m_traderapi;}public class demo { static{ System.loadLibrary("thosttraderapi"); System.loadLibrary("thosttraderapi_wrap"); } final static String ctp1_TradeAddress = "tcp://180.168.146.187:10000"; public static void main(String[] args) { // TODO Auto-generated method stub CThostFtdcTraderApi traderApi = CThostFtdcTraderApi.CreateFtdcTraderApi(); TraderSpiImpl pTraderSpi = new TraderSpiImpl(traderApi); traderApi.RegisterSpi(pTraderSpi); traderApi.RegisterFront(ctp1_TradeAddress); traderApi.SubscribePublicTopic(THOST_TE_RESUME_TYPE.THOST_TERT_RESTART); traderApi.SubscribePrivateTopic(THOST_TE_RESUME_TYPE.THOST_TERT_RESTART); traderApi.Init(); traderApi.Join(); return; }}
本人所编译的CTP0606版本的交易、行情Java API
,点击下载。声明:仅是个人爱好编译,对此API引起的您的任何损失不负责任。
各位注意一下,在上传的win32资源中,mdapi里的一个dll上传错了,只要将ctp官网中的“thostmduserapi.dll”替换掉“thosttraderapi.dll”就可以运行了。是我粗心上传错了,抱歉!
- CTP JAVA API(JCTP)编译(利用Swig封装C++动态库)windows版
- CTP JAVA_API(JCTP)编译(利用Swig封装C++动态库)linux版64位
- CTP Python API(利用Swig 封装)Windows版(traderapi)
- CTP Python API(利用Swig 封装)Windows版(mduserapi)
- 通过Swig封装JAVA Native Interface调用C++动态库
- SWIG封装C代码
- swig 把c/c++ 封装成python可调用的so文动态链接库
- SWIG,把C/C++ API 导出成Java,C#,Python,Ruby,Php的类库
- 用Swig封装C/C++
- 用Swig封装C/C++
- 利用 SWIG 转换 C/C++ 接口到 Java 接口
- SWIG and Python(用SWIG将C/C++封装为Python扩展模块)
- 利用JDK1.6API 动态编译JAVA源文件
- Swig编译C代码供java调用实例
- java/android 使用swig编译c/c++ 代码类型转换
- Swig封装C/C++——介绍
- 利用SWIG将C/C++库包装成Ruby模块
- Android NDK项目中使用SWIG生成JAVA类和C/C++封装代码
- Tiny6410 Android2.3.4源码编译问题解决
- Linux执行Shell脚本问题
- 使用IMP报错:参数错误
- 理解MySQL——索引与优化
- I/O空间映射
- CTP JAVA API(JCTP)编译(利用Swig封装C++动态库)windows版
- android MagicIndicator 指示器简单使用
- android 5.0效果,快捷使用方法
- 关于手机android版本的动画
- myeclipse保存时build workspace缓慢解决方案
- 关于cocos2d-x 3.3网格特效笔记
- 接口和抽象类有什么区别
- 打电话,发送消息,发送邮件及附件的代码实现
- bzoj3609