zoukankan      html  css  js  c++  java
  • C#调用行情接口API 转 武胜

    C#调用行情接口API

              很早就已经通过了C#调用行情接口API的实现(见以前的日志),但是还是有人没有搞明白,在这里就讲讲如何实现的。
    首先,根据提供的stockdrv.h的信息,将数据结构移植到C#代码中。
    1.数据结构定义
       // <summary>
        // stockdrv.dll 的摘要说明。
        // </summary>
        //
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
        public struct tagSTOCK_STRUCTEx
        {
           public byte m_type;     // stock's type, see enum StockType
           [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
           public char[] m_code;    // stock code
        }
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
        public struct tagRCV_REPORT_STRUCTEx
        {
            public UInt16 m_cbSize;                                    // 结构大小
            public Int32 m_time;                                       // 交易时间
            public UInt16 m_wMarket;                                   // 股票市场类型
    //m_szLabel,m_szName 的定义根据自己喜好可以定义成
             [MarshalAs(   UnmanagedType.ByValArray, SizeConst=10)]   
            public   char[]  m_szLabel; //   代码,以'\0'结尾   数组大小为STKLABEL_LEN,在c++描述中为char[10]     
             [MarshalAs(   UnmanagedType.ByValArray,   SizeConst=32)]   
             public   char[]  m_szName;  //   名称,以'\0'结尾   数组大小为STKNAME_LEN,在c++描述中为char[32]    
    /*  也可以定义成
            [MarshalAs(UnmanagedType.ByValTStr,SizeConst = 10)]
            public string m_szLabel;                               // 代码,以'\0'结尾  数组大小为STKLABEL_LEN,在c++描述中为char[10]    
            [MarshalAs(UnmanagedType.ByValTStr,SizeConst = 32)]
            public string m_szName;                                // 名称,以'\0'结尾 组大小为STKNAME_LEN,在c++描述中为char[32]    
            */
            public Single m_fLastClose;                           // 昨收
            public Single m_fOpen;                                // 今开
            public Single m_fHigh;                                // 最高
            public Single m_fLow;                                 // 最低
            public Single m_fNewPrice;                            // 最新
            public Single m_fVolume;                              // 成交量
            public Single m_fAmount;                              // 成交额
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
            public Single[] m_fBuyPrice;                         // 申买价1,2,3
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
            public Single[] m_fBuyVolume;                        // 申买量1,2,3
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
            public Single[] m_fSellPrice;                        // 申卖价1,2,3
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
            public Single[] m_fSellVolume;                       // 申卖量1,2,3
            public Single m_fBuyPrice4;                          // 申买价4
            public Single m_fBuyVolume4;                         // 申买量4
            public Single m_fSellPrice4;                         // 申卖价4
            public Single m_fSellVolume4;                        // 申卖量4
            public Single m_fBuyPrice5;                          // 申买价5
            public Single m_fBuyVolume5;                         // 申买量5
            public Single m_fSellPrice5;                         // 申卖价5
            public Single m_fSellVolume5;                        // 申卖量5
           ......          其他项的定义
        };
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
        public struct tagRCV_FILE_HEADEx
        {
            public int m_dwAttrib;                      // 文件子类型
            public int m_dwLen;                         // 文件长度
            public int m_dwSerialNoorTime;              //文件序列号或时间.
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 260)]
            char[] m_szFileName;                        // 文件名 or URL
        }
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi , Pack=1)]
        public struct tagRCV_DATA
        {
            public int m_wDataType;                     // 文件类型
            public int m_nPacketNum;                    // 记录数,参见注一
            [MarshalAs(UnmanagedType.Struct)]
            public tagRCV_FILE_HEADEx m_File;          // 文件接口
            public int m_bDISK;                        // 文件是否已存盘的文件
            public IntPtr m_pData;
        } ;
     
      以上的定义关键点之一,是说明Pack,如果不说明,在后面的数据处理时,会遇到点问题。
     如在C#里定义的数据结构,取得结构长度,与C++的结构长度不一致。
    究其原因,就是没有对齐处理或二者对齐处理方式不一致。
     
     2.API借口定义
        public class Stockdrv
        {
    // 宏定义直接根据C++的改写过来即可
            public const int RCV_WORK_SENDMSG = 4;     // 工作方式类型定义-窗口消息方式
            public const int RCV_MSG_STKDATA = 0x8001; //指定使用的消息
            public const int RCV_REPORT    = 0x3f001234; //股票行情 
            public const UInt32 EKE_HEAD_TAG = 0xffffffff; //数据头结构标记
             。。。。。。
     
    // 接口函数的定义,根据提供stockdrv.h 按照如下改写即可
    // 偶提供的是UNICODE版本的DLL,如果不是CharSet 改为 CharSet.Ansi 即可
    // 显式说明,可以避免一些不必要的麻烦
            [DllImport("stockdrv.dll")]
            public static extern int Stock_Init(IntPtr nHwnd, int nMsg, int nWorkMode);
            [DllImport(@"stockdrv.dll",CharSet = CharSet.Unicode) ]
            public static extern int GetStockByCodeEx (string strCode,int nMarket,ref tagRCV_REPORT_STRUCTEx sRcvReort);
            [DllImport("stockdrv.dll")]
            public static extern int SetupReceiver(bool bSetup);
            [DllImport("stockdrv.dll")]
            public static extern int GetTotalNumber();
            [DllImport("stockdrv.dll")]
            public static extern int Stock_Quit(int hWnd);
            [DllImport(@"stockdrv.dll" ,CharSet = CharSet.Unicode)]
            public static extern int Stock_Init_Nodialog(IntPtr hWnd, int Msg, int nWorkMode, string szAddress, int nPort, string  szUser, string  szPasswd,string szSecAddress, int nSecPort,int nAuth );
            [DllImport("stockdrv.dll")]
            public static extern int  IsEngineWorking( );
            [DllImport("stockdrv.dll")]
            public static extern int SetAutoReport( int bAutoReport );
            [DllImport("stockdrv.dll")]
            public static extern int RequestStockData(int nDataType, tagSTOCK_STRUCTEx [] pStocks, int nSize, int nKType, int nDataCount);
    。。。。。。。。 // 余下的按此方式写就是了,用不到的也可以不写哦!
     
            public Stockdrv()
            {
                //
                // TODO: 在此处添加构造函数逻辑
                //
            }
        }
    ///---------------------------------------------------------------------------------------
    }
     
    3. 调用API
       采用数据共享引用时
        // 数据共享引用,调用 C++ 中的接口函数
         Stockdrv.Stock_Init(this.Handle, Stockdrv.RCV_MSG_STKDATA, Stockdrv.RCV_WORK_SENDMSG);
         Stockdrv.SetupReceiver(false);
         这种方式一般不使用了,提供该方式主要为了兼容的缘故
     
       网络直接连接
        int lResult = Stockdrv.Stock_Init_Nodialog(this.Handle, Stockdrv.RCV_MSG_STKDATA, Stockdrv.RCV_WORK_SENDMSG,.......);
        Stockdrv.SetupReceiver(false);
        接下来请求数据
               tagSTOCK_STRUCTEx[] pStocks = new tagSTOCK_STRUCTEx[1];
                string s = "999999;
                pStocks[0].m_code = s.ToCharArray(0, s.Length);
                pStocks[0].m_type = 0x10;
                Stockdrv.RequestStockData(Stockdrv.RCV_REPORT, pStocks, 1, 0, 0);
     
    4.数据接收
        只要对数据接收,重载 WndProc 即可,代码如下:
      /// //////////////////////////////////////////////////////////
            /// 重载虚拟 WndProc 接收消息的窗口的消息处理过程,以截获任何消息
            /// /////////////////////////////////////////////////////////       
            protected override void WndProc(ref Message m)
            {
                if ((int)m.Msg == Stockdrv.RCV_MSG_STKDATA)
                {           
                    tagRCV_DATA recvData = (tagRCV_DATA)Marshal.PtrToStructure(m.LParam, typeof(tagRCV_DATA));
                    if ((int)m.WParam == Stockdrv.RCV_REPORT) //行情数据
                    {
                        m_bInitOK = true;                
                        tagRCV_REPORT_STRUCTEx ReprotData;
                        int recLength ;
                        recLength = Marshal.SizeOf(typeof(tagRCV_REPORT_STRUCTEx))  // 需要实际长度
                        for (int i = 0; i < recvData.m_nPacketNum; i++)
                        {
                            //结构中如果没有说明 Pack =1,需要前移 -2
                           // 这也是许多人感觉为啥差-2原因, 在 VB6.0 也是如此,VB.NET如果没有说明Pack =1,也是同样的问题
                            //ReprotData = (tagRCV_REPORT_STRUCTEx)Marshal.PtrToStructure(new IntPtr((int)recvData.m_pData + i * recLength-2), typeof(tagRCV_REPORT_STRUCTEx));

                            //结构中需要说明 Pack =1
                            ReprotData = (tagRCV_REPORT_STRUCTEx)Marshal.PtrToStructure(new IntPtr((int)recvData.m_pData + i * recLength ), typeof(tagRCV_REPORT_STRUCTEx));
                               //  数据计算与分析 省略                        
                                。。。。。。。。。
                            }
                        }
                    }
                    return;
                }         
                base.WndProc(ref m); // 调用基类成员函数!   
            }
       至此,已经完成说明了如何在C#中调用API,相信大家可以开发出适合自己的股软分析软件!
       如有不对之处,请大家多指教!
  • 相关阅读:
    合约广告系统-在线分配问题
    合约广告系统-合约广告系统
    合约广告系统-常用广告系统开源工具
    knnsearch
    ISOMAP和MDS降维
    dijstra算法
    矩阵大于某个数置零
    mathtype 公式分节隐藏
    fifo 实现问题
    vhdl 数据类型转换 使用IEEE标准库numeric_std 需要进行两次转换 use ieee.numeric_std.all;
  • 原文地址:https://www.cnblogs.com/zeroone/p/2830078.html
Copyright © 2011-2022 走看看