(转)C#封装CTP
一、CTPFutrueProvider
https://github.com/fouvy/CTPFutrueProvider
动态链接库:CTPWrapper 项目概述
应用程序向导已为您创建了此 CTPWrapper DLL。
本文件概要介绍组成 CTPWrapper 应用程序的每个文件的内容。
CTPWrapper.vcproj
这是使用应用程序向导生成的 VC++ 项目的主项目文件。
它包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
CTPWrapper.cpp
这是主 DLL 源文件。
其他标准文件:
StdAfx.h, StdAfx.cpp
这些文件用于生成名为 CTPWrapper.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。
其他注释:
应用程序向导使用“TODO:”指示应添加或自定义的源代码部分。
二、PInvoke的方式
今天主要讲以下的方式:
http://www.360doc.com/content/14/0211/00/3218170_351502832.shtml
从C#的托管代码中,调用C++的非托管代码,主要是使用PInvoke的方式,但CTP的API接口中存在以下两个特点,使我们无法直接调用
1、各种请求(Req函数)是Api类的成员函数,而不是静态函数
2、各种响应,是需要继承Spi类之后,才能在重写的虚函数(是叫这名字吧。。。)中得到回传数据
针对这两个特点,我使用的方法是
1、新建WIN32项目(项目名:CTPWrapper),将Api类的成员函数扩展成静态函数,如:
Code:
///创建TraderApi
///@param pszFlowPath 存贮订阅信息文件的目录,默认为当前目录
///@return 创建出的UserApi
extern "C" CTPWRAPPER_API void* CreateTraderApi(const char *pszFlowPath)
{return CThostFtdcTraderApi::CreateFtdcTraderApi(pszFlowPath);
};///注册前置机网络地址
///@param pszFrontAddress:前置机网络地址。
///@remark 网络地址的格式为:“protocol://ipaddress:port”,如:”tcp://127.0.0.1:17001”。
///@remark “tcp”代表传输协议,“127.0.0.1”代表服务器地址。”17001”代表服务器端口号。
extern "C" CTPWRAPPER_API void TraderRegisterFront(void *instance,char *pszFrontAddress)
{((CThostFtdcTraderApi *)instance)->RegisterFront(pszFrontAddress);
};
其中的CTPWRAPPER_API 是
Code:
#define CTPWRAPPER_API __declspec(dllexport)
就像这样,实现了两个标准的WIN32API,将其编译成DLL,从C#中就可以直接调用了。
C#中定义PInvoke方法如下
Code:
[DllImport("CTPWrapper.dll")]internal static extern IntPtr CreateTraderApi(string pszFlowPath);[DllImport("CTPWrapper.dll")]internal static extern void TraderRegisterFront(IntPtr hTrader, String address);
在C#中创建并使用TraderApi
Code:
IntPtr _instance = CreateTraderApi("");
TraderRegisterSpi(_instance, this._listener.Instance);
2、使用函数指针从C++的函数中调用C#的方法
为保证C++的函数能够正确的调用C#的方法,函数指针的构成必须一致,因此分别在C++和C#中定义以下内容:
Code:
C++
///登录请求响应
typedef void (WINAPI *OnRspUserLoginCallback)(CThostFtdcRspUserLoginField *pRspUserLogin, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) ;
C#
Code:
public delegate void UserLoginCallback(IntPtr pRspUserLogin, IntPtr pRspInfo, int nRequestID, [MarshalAs(UnmanagedType.U1)]bool bIsLast);
(这里注意下bool类型的定义,在这里我被郁闷了好久:()
然后在创建Spi类的时候将C#的回调函数指针作为参数传到C++中
Code:
C++中Spi的构造函数
CTPTraderSpi::CTPTraderSpi(OnRspUserLoginCallback callback)
{this->m_OnRspUserLoginCallback = callback;
}
同1的方法,将构造函数扩展为WIN32API
Code:
extern "C" CTPWRAPPER_API void* WINAPI CreateTraderSpiClass(OnRspUserLoginCallback callback)
{CTPTraderSpi *spi = new CTPTraderSpi(callback);return (void*)spi;
}
这样,在C++中得到响应时,就可以调用C#的方法了
Code:
///登录请求响应
void CTPTraderSpi::OnRspUserLogin(CThostFtdcRspUserLoginField *pRspUserLogin, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{if(this->m_OnRspUserLoginCallback){(this->m_OnRspUserLoginCallback)(pRspUserLogin ,pRspInfo,nRequestID,bIsLast);}
}
在C#中,这样使用
Code:
UserLoginCallback userLoginCallback = new UserLoginCallback(this.OnUserLogin);_instance = CreateTraderSpiClass(userLoginCallback);
OK,到这里,最最核心的东西已经说完了,剩下的都是些技巧和体力活了
比如Spi的回调函数有很多,总不可能在C#中创建好了再一个个传到C++里,怎办呢?其实我是用了个Struct,包好了一起传的
Code:
/// <summary>/// 回调函数指针结构/// </summary>[StructLayout(LayoutKind.Sequential)]internal struct CTPTraderSpiCallbackStruct{///当客户端与交易后台建立起通信连接时(还未登录前),该方法被调用。internal FrontConnectedCallback FrontConnectedCallback;///当客户端与交易后台通信连接断开时,该方法被调用。当发生这个情况后,API会自动重新连接,客户端可不做处理。///@param nReason 错误原因/// 0x1001 网络读失败/// 0x1002 网络写失败/// 0x2001 接收心跳超时/// 0x2002 发送心跳失败/// 0x2003 收到错误报文internal FrontDisconnectedCallback FrontDisconnectedCallback;///心跳超时警告。当长时间未收到报文时,该方法被调用。///@param nTimeLapse 距离上次接收报文的时间internal HeartBeatWarningCallback HeartBeatWarningCallback;///登录请求响应internal UserLoginCallback UserLoginCallback;///登出请求响应internal UserLogoutCallback UserLogoutCallback;}
以下略
剩下还有一些细节问题,回头再慢慢说好了,整个过程被我封装成了两个工程
C++:CTPWrapper
C#:CTPInterop
由于还有很多工作没有完成,也就不发布出来了,有兴趣的朋友可以通过邮件和我联系,我把工程代码发给你
mail:lumen.xh@gmail.com
当然,如果有朋友愿意和我一起把剩下的部分建立起来的话,那就更好了:D
(转)C#封装CTP相关推荐
- 上海期货交易所CTP行情和交易接入
发布时间:2018-09-25 技术:C++11,动态库的制作 概述 CTP的接入Demo 详细 代码下载:http://www.demodashi.com/demo/14125.html 本文档不介 ...
- CTP程序化交易入门系列之六:报单(一)
行情(mduserapi)这一块终于介绍的差不多了,下面着重介绍交易(traderapi)相关.再次强调两点: 一.交易和行情是完全独立的,互不干扰: 二.本系列用Python版本讲解,主要考虑到Py ...
- vn.py源码解读(五、主引擎代码分析----CTP模块)
上一篇文章讲了MainEngine中的初始化函数,重点是DataEngine的讲解.有了对行情数据的处理,还需要有行情数据的来源.在MainEngine的初始化函数后面的一个函数就是addGatewa ...
- java ctp行情_javaCtp: java版本期货程序化交易系统,包括行情服务,交易服务会逐步完善...
java_vnpy 介绍 java版本期货程序化交易系统,包括行情服务,交易服务会逐步完善,CTP版本上期技术官网下载6.3.15 穿透式, 目前项目无架构设计,只针对ctp进行封装调用,实现基本交易 ...
- 量化交易数据接口如何获取实时行情数据的呢?
基本都是自己封装CTP接口,程序端实现多账户.多策略的行情信号接收和委托提交/回报处理.也可以用 QuantBox/QuantBox_XAPI · GitHub 这样的封装的比较好.多接口统一API的 ...
- 通达信期货ctp交易接口进行封装对接?
CTP接口除官方发布的C++动态库外,很多人也提供了Python.Java.C#等各主流语言的接口,可搜索相应的开发方法.一个连接能够查询的股票数量是有限的,性能也不高,但是可以创建多个api实例并发 ...
- ctp java_上期CTP 封装JAVA API window Swig
1 首先在http://www.sfit.com.cn/5_2_DocumentDown.htm 下载CTP 后得到下面这些文件 2 我们选用32位版本20160606_tradeapi_windo ...
- 上期技术CTPAPI封装COM组件ctp开放平台openctp环境7_24小时x64组件python_delphi调用演示程序
源码下载地址:https://gitee.com/topview999/TopViewQHTCtpCom 新修改后的python调用COM组件,pyside2制作的UI界面.体验一下远超VeighNa ...
- java ctp行情_java-ctp
java-ctp java包装的上期ctp,用swig技术实现. 2014-4-7 10:09:11 项目已经搭建好,上传到这里方法还不会.时间比较紧,有空上传上来. 2014-7-31 22:43: ...
- 封装时间转换工具类_利用swig封装C++的dll为C#方便使用
使用C++开发界面,时间效率上来说,不如C#开发的快和方便.但是CTP的库是C++的,并没有C#的库,网上也有人用C#的PINVOKE的方式将C++的函数一个个转换为C#能用的接口,我是看了下,原理o ...
最新文章
- 不同版本的Chrom浏览器对应的ChromDriver的版本
- Seafile - 最好的 Dropbox 开源替代,面向团队而设计
- expressjs路由和Nodejs服务器端发送REST请求 - - ITeye博客
- 上周五,小编参加了一场高大上的“9”会
- pandas to_sql保存数据到数据库后,添加自增长的主键ID(PRIMARY KEY)
- 双向循环链表涉及双向指针的基本操作(C语言)
- 国内外公有云对比:功能介绍、性能测试
- 商业智能应用的五大步骤
- 如何连接局域网_Minecraft我的世界局域网联机问题(windows平台)
- Mathematica/偏导数/最小二乘法(线性回归)
- vistor和tsmserver不在同一台机器上的连接问题
- 【BZOJ4372】烁烁的游戏(点分树)
- 匿名认证(Anonymous Authentication)
- 一文带你了解学习python的用处及好处,建议收藏
- html ---烟花
- Linux 解压缩文件到指定目录
- 音视频QoE核心指标
- 985毕业,半路出家28岁进军Java,坚持奋斗了三年现如今年薪36W+
- 百度云盘云知梦php_[云知梦]WEB前端开发_WEB前端新手入门视频教程[百度云盘]
- es教程——地图搜索