由于还是利用.net framework3.0,并未使用4.0,所以对于C++编写的接口仍需采用pinvoke方式。
首先将c++中结构体转换为c#中结构体
例子
C++
typedef struct tagRCV_EKE_HEADEx { DWORD m_dwHeadTag; // = EKE_HEAD_TAG WORD m_wMarket; // 市场类型 char m_szLabel[STKLABEL_LEN];// 股票代码 }RCV_EKE_HEADEx,*PRCV_EKE_HEADEx; typedef union tagRCV_HISTORY_STRUCTEx { struct { my_time_t m_time; //UCT float m_fOpen; //开盘 float m_fHigh; //最高 float m_fLow; //最低 float m_fClose; //收盘 float m_fVolume; //量 float m_fAmount; //额 union { struct { WORD m_wAdvance; //涨数,仅大盘有效 WORD m_wDecline; //跌数,仅大盘有效 }; float m_fOI; }; }; RCV_EKE_HEADEx m_head; }RCV_HISTORY_STRUCTEx,*PRCV_HISTORY_STRUCTEx;
C#
//补充数据头 [StructLayout(LayoutKind.Sequential)] public struct RCV_EKE_HEADEx { public uint m_dwHeadTag; // = EKE_HEAD_TAG public ushort m_wMarket; // 市场类型 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] public char[] m_szLabel; // 股票代码 } //补充日线数据 [StructLayout(LayoutKind.Explicit)] public struct RCV_HISTORY_STRUCTEx { [FieldOffset(4)] public int m_time; [FieldOffset(8)] public Single m_fOpen; //开盘 [FieldOffset(12)] public Single m_fHigh; //最高 [FieldOffset(16)] public Single m_fLow; //最低 [FieldOffset(20)] public Single m_fClose; //收盘 [FieldOffset(24)] public Single m_fVolume; //量 [FieldOffset(28)] public Single m_fAmount; //额 [FieldOffset(32)] public UInt16 m_wAdvance; //涨数,仅大盘有效 [FieldOffset(34)] public UInt16 m_wDecline; //跌数,仅大盘有效 [FieldOffset(36)] public Single m_fOI; [FieldOffset(40)] public RCV_EKE_HEADEx m_head; }
第二步:注册函数
例子
[DllImport(@"e:/skyjet.dll")] private static extern int Stock_Init(IntPtr hWnd, uint Msg, int nWorkMode);
第三步就是接受数据了
下面是我改写C#版本接收数据的代码
/// <summary> /// 获取数据 /// </summary> public void GetData() { //RCV_DATA也是接口所使用的结构体,以下ReportModel下的都是使用的结构体或者常量 ReportModel.RCV_DATA pHeader = (ReportModel.RCV_DATA)msg.GetLParam(typeof(ReportModel.RCV_DATA)); if (pHeader.ptr != IntPtr.Zero) { switch (msg.WParam.ToInt32()) { case ReportModel.RCV_REPORT: { for (int i = 0; i < pHeader.m_nPacketNum; i++) { //report就是一条实时行情数据 ReportModel.RCV_REPORT_STRUCTExV3 report = (ReportModel.RCV_REPORT_STRUCTExV3)Marshal.PtrToStructure(new IntPtr((int)pHeader.ptr + 158 * i), typeof(ReportModel.RCV_REPORT_STRUCTExV3)); //将实时数据存入自己的集合中,或者做别的数量 } //存储实时行情 break; } case ReportModel.RCV_FILEDATA: { switch (pHeader.m_wDataType) { // 补日线数据; case ReportModel.FILE_HISTORY_EX: //行情中的商品名称等数据存入此处(即补充的数据头) currency = (ReportModel.RCV_EKE_HEADEx)Marshal.PtrToStructure(new IntPtr((int)pHeader.ptr), typeof(ReportModel.RCV_EKE_HEADEx)); for (int i = 0; i < pHeader.m_nPacketNum; i++) { //日线数据 ReportModel.RCV_HISTORY_STRUCTEx history = (ReportModel.RCV_HISTORY_STRUCTEx)Marshal.PtrToStructure(new IntPtr((int)pHeader.ptr + 28 + 32 * i), typeof(ReportModel.RCV_HISTORY_STRUCTEx)); //时间日期计算 new DateTime(1970, 1, 1, 8, 0, 0, DateTimeKind.Unspecified).Add(TimeSpan.FromTicks(history.m_time * TimeSpan.TicksPerSecond)); //将日线数据存入自己的集合中,或处理数据 } //存储数据 break; } default: break; } }
C++中CTime类型和C#中DateTime类型转换利用上面代码中DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Unspecified).Add(TimeSpan.FromTicks(history.m_time * TimeSpan.TicksPerSecond));因为是UTC时间,所以第四个参数改为8(增加8小时)。
如果需要相应完整代码,可以email:huimin1984@citiz.net
如果代码有问题,或者可以改进,请留言,谢谢帮助。