您的位置:首页 > 编程语言 > C语言/C++

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

2016-11-16 14:43 681 查看
前言:

目前上期技术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
版本,点击下载

安装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
可调用接口的库文件。

这所有完成之后,
C++
工程中文件应该如下:



接下来还需要对
thosttraderapi_wrap.cpp
文件进行一些编辑:

将如下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

拷贝到你电脑环境变量
path
路径底下,如果自己不清楚,可以在
Java
中用如下代码获得

System.out.println(System.getProperty("java.library.path"));


我直接拷贝到了
\Java\jdk1.8.0_111
底下。

完整的tradeapidemo代码如下:

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:10010";
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;
}
}


行情mdapidemo如下

package csdnmdapidemo;

import test.thostmduserapi.*;

class mdspiImpl extends CThostFtdcMdSpi{
final static String m_BrokerId = "8000";
final static String m_UserId = "000326";
final static String m_InvestorId = "000326";
final static String m_PassWord = "1";
final static String m_TradingDay = "20161111";
final static String m_AccountId = "000326";
final static String m_CurrencyId = "CNY";
mdspiImpl(CThostFtdcMdApi mdapi)
{
m_mdapi =  mdapi;
}

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);
m_mdapi.ReqUserLogin(field, 0);

}

public void OnRspUserLogin(CThostFtdcRspUserLoginField pRspUserLogin, CThostFtdcRspInfoField pRspInfo, int nRequestID, boolean bIsLast) {
if (pRspUserLogin != null) {
System.out.printf("Brokerid[%s]\n",pRspUserLogin.getBrokerID());
}

String[] instruementid = new String[1];
instruementid[0]="sc1308";
m_mdapi.SubscribeMarketData(instruementid,1);
}

public void OnRtnDepthMarketData(CThostFtdcDepthMarketDataField pDepthMarketData) {
if (pDepthMarketData != null)
{
System.out.printf("AskPrice1[%f]BidPrice1[%f]\n",
pDepthMarketData.getAskPrice1(),pDepthMarketData.getBidPrice1());
}
else
{
System.out.printf("NULL obj\n");
}
}
private CThostFtdcMdApi m_mdapi;
}

public class MdapiDemo {
static{
System.loadLibrary("thostmduserapi");
System.loadLibrary("thostmduserapi_wrap");
}
final static String ctp1_MdAddress = "tcp://172.19.125.39:50235";
public static void main(String[] args) {
// TODO Auto-generated method stub
CThostFtdcMdApi mdApi = CThostFtdcMdApi.CreateFtdcMdApi();
mdspiImpl pMdspiImpl = new mdspiImpl(mdApi);
mdApi.RegisterSpi(pMdspiImpl);
mdApi.RegisterFront(ctp1_MdAddress);
mdApi.Init();
mdApi.Join();
return;
}
}


本人所编译的CTP0606版本的交易、行情
Java API
点击下载。声明:仅是个人爱好编译,对此API引起的您的任何损失不负责任。

各位注意一下,在上传的win32资源中,mdapi里的一个dll上传错了,只要将ctp官网中的“thostmduserapi.dll”替换掉“thosttraderapi.dll”就可以运行了。是我粗心上传错了,抱歉!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  windows api java C++