Last active
July 6, 2017 08:10
-
-
Save kwedr/9a862582a016319949e63eca8b013428 to your computer and use it in GitHub Desktop.
群益API with cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include "stdafx.h" | |
| #include <iostream> | |
| #include <atlbase.h> | |
| #include <atlcom.h> | |
| #include <atlcomcli.h> | |
| #include <map> | |
| #include <queue> | |
| #include <mutex> | |
| //#import "SKCOM.tlb" | |
| #import "D:\\dll\\x64\\SKCOM.dll" | |
| using namespace SKCOMLib; | |
| template <class T> | |
| class SafeQueue | |
| { | |
| public: | |
| SafeQueue(void) | |
| : q() | |
| , m() | |
| , c() | |
| {} | |
| ~SafeQueue(void) | |
| {} | |
| // Add an element to the queue. | |
| void enqueue(T t) | |
| { | |
| std::lock_guard<std::mutex> lock(m); | |
| q.push(t); | |
| c.notify_one(); | |
| } | |
| // Get the "front"-element. | |
| // If the queue is empty, wait till a element is avaiable. | |
| T dequeue(void) | |
| { | |
| std::unique_lock<std::mutex> lock(m); | |
| while (q.empty()) | |
| { | |
| // release lock as long as the wait and reaquire it afterwards. | |
| c.wait(lock); | |
| } | |
| T val = q.front(); | |
| q.pop(); | |
| return val; | |
| } | |
| bool empty() { return q.empty (); } | |
| private: | |
| std::queue<T> q; | |
| mutable std::mutex m; | |
| std::condition_variable c; | |
| }; | |
| class Job | |
| { | |
| public: | |
| enum { | |
| Quote_Connect = 1, | |
| Quote_EnterMonitor = 2, | |
| GetStockByIndex = 3, | |
| GetStockByIndexResult = 4, | |
| OnNotifyQuote = 5, | |
| }; | |
| int do_type; | |
| int nValue1; | |
| int nValue2; | |
| SKSTOCK* Stock; | |
| Job(int value) | |
| : do_type (value) | |
| , nValue1 (0) | |
| , nValue2 (0) | |
| , Stock (NULL) | |
| { | |
| } | |
| }; | |
| SafeQueue<Job> q; | |
| class StockBot; | |
| class SKCenterLibEventWrapper : public IDispEventSimpleImpl<1, SKCenterLibEventWrapper, &__uuidof (_ISKCenterLibEvents) > | |
| { | |
| public: | |
| // now you need to declare a sink map - a map of methods handling the events | |
| BEGIN_SINK_MAP(SKCenterLibEventWrapper) | |
| SINK_ENTRY_INFO(1, __uuidof (_ISKCenterLibEvents), 0x1, OnTimer, &CallBackOnTimer) | |
| END_SINK_MAP() | |
| static _ATL_FUNC_INFO CallBackOnTimer; | |
| StockBot* Bot; | |
| SKCenterLibEventWrapper(StockBot* bot) | |
| : IDispEventSimpleImpl<1, SKCenterLibEventWrapper, &__uuidof (_ISKCenterLibEvents) >() | |
| , Bot (bot) | |
| { | |
| } | |
| STDMETHOD(OnTimer)(int timer) | |
| { | |
| printf("%d\n", timer); | |
| return 0; | |
| } | |
| }; | |
| _ATL_FUNC_INFO SKCenterLibEventWrapper::CallBackOnTimer = { CC_STDCALL, VT_EMPTY, 1, {VT_I4} }; | |
| class SKQuoteLibEventWrapper : public IDispEventSimpleImpl<1, SKQuoteLibEventWrapper, &__uuidof (_ISKQuoteLibEvents) > | |
| { | |
| public: | |
| // now you need to declare a sink map - a map of methods handling the events | |
| BEGIN_SINK_MAP(SKQuoteLibEventWrapper) | |
| SINK_ENTRY_INFO(1, __uuidof (_ISKQuoteLibEvents), 0x1, OnConnect, &CallBackOnConnect) | |
| SINK_ENTRY_INFO(1, __uuidof (_ISKQuoteLibEvents), 0x2, OnNotifyQuote, &CallBackOnNotifyQuote) | |
| END_SINK_MAP() | |
| static _ATL_FUNC_INFO CallBackOnConnect; | |
| static _ATL_FUNC_INFO CallBackOnNotifyQuote; | |
| StockBot* Bot; | |
| SKQuoteLibEventWrapper(StockBot* bot) | |
| :IDispEventSimpleImpl<1, SKQuoteLibEventWrapper, &__uuidof (_ISKQuoteLibEvents) > () | |
| , Bot(bot) | |
| { | |
| } | |
| STDMETHOD(OnConnect)(int nKind, int nCode) | |
| { | |
| Job j(Job::Quote_Connect); | |
| j.nValue1 = nKind; | |
| j.nValue2 = nCode; | |
| q.enqueue(j); | |
| return 0; | |
| } | |
| STDMETHOD(OnNotifyQuote)(int sMarketNo, int sStockIdx) | |
| { | |
| Job j(Job::GetStockByIndexResult); | |
| j.nValue1 = sMarketNo; | |
| j.nValue2 = sStockIdx; | |
| q.enqueue(j); | |
| return 0; | |
| } | |
| }; | |
| _ATL_FUNC_INFO SKQuoteLibEventWrapper::CallBackOnConnect = { CC_STDCALL, VT_EMPTY, 2, {VT_I4, VT_I4} }; | |
| _ATL_FUNC_INFO SKQuoteLibEventWrapper::CallBackOnNotifyQuote = { CC_STDCALL, VT_EMPTY, 2, {VT_I4, VT_I4} }; | |
| class SKCOMWapper | |
| { | |
| public: | |
| ISKCenterLibPtr SKCenterLibPtr; | |
| ISKQuoteLibPtr SKQuoteLibPtr; | |
| SKCenterLibEventWrapper* SKCenterLibEventsWp; | |
| SKQuoteLibEventWrapper* SKQuoteLibEventsWp; | |
| StockBot* Bot; | |
| SKCOMWapper(StockBot* bot): | |
| Bot (bot) | |
| { | |
| SKCenterLibPtr.CreateInstance(__uuidof(SKCenterLib)); | |
| SKCenterLibEventsWp = new SKCenterLibEventWrapper(bot); | |
| SKCenterLibEventsWp->DispEventAdvise(SKCenterLibPtr); | |
| SKQuoteLibPtr.CreateInstance(__uuidof(SKQuoteLib)); | |
| SKQuoteLibEventsWp = new SKQuoteLibEventWrapper(bot); | |
| SKQuoteLibEventsWp->DispEventAdvise(SKQuoteLibPtr); | |
| } | |
| ~SKCOMWapper() | |
| { | |
| SKCenterLibEventsWp->DispEventUnadvise(SKCenterLibPtr); | |
| delete SKCenterLibEventsWp; | |
| SKCenterLibPtr->Release(); | |
| SKCenterLibPtr = NULL; | |
| SKQuoteLibEventsWp->DispEventUnadvise(SKQuoteLibPtr); | |
| delete SKQuoteLibEventsWp; | |
| SKQuoteLibPtr->Release(); | |
| SKQuoteLibPtr = NULL; | |
| } | |
| }; | |
| class StockBot | |
| { | |
| public: | |
| SKCOMWapper* SKCOM; | |
| std::string StockNo; | |
| std::map <BSTR, SKSTOCK*> Stock; | |
| StockBot(std::string stockno) | |
| { | |
| StockNo = stockno; | |
| SKCOM = new SKCOMWapper(this); | |
| } | |
| void DoLogin(const char* account, const char* pwd) | |
| { | |
| BSTR str_account = _bstr_t(account).Detach(); | |
| BSTR str_pwd = _bstr_t(pwd).Detach(); | |
| HRESULT ret = SKCOM->SKCenterLibPtr->SKCenterLib_Login(str_account, str_pwd); | |
| ::SysFreeString(str_account); | |
| ::SysFreeString(str_pwd); | |
| Job j((int)Job::Quote_EnterMonitor); | |
| q.enqueue(j); | |
| } | |
| void SKQuoteLibOnConnection(int nKind, int nCode) | |
| { | |
| if (nKind == 3003 && nCode == 0) | |
| { | |
| q.enqueue(Job(Job::GetStockByIndex)); | |
| } | |
| printf("OnConnection Kind:%d Code:%d\n", nKind, nCode); | |
| } | |
| void DoOnNotifyQuote(int sMarketNo, int sIndex) | |
| { | |
| SKSTOCK* s = new SKSTOCK(); | |
| SKCOM->SKQuoteLibPtr->SKQuoteLib_GetStockByIndex(sMarketNo, sIndex, s); | |
| Job j(Job::OnNotifyQuote); | |
| j.Stock = s; | |
| q.enqueue(j); | |
| } | |
| void DoGetStockByIndex() | |
| { | |
| BSTR str_stock = _bstr_t(StockNo.c_str ()).Detach(); | |
| short no = -1; | |
| long ret = SKCOM->SKQuoteLibPtr->SKQuoteLib_RequestStocks (&no, str_stock); | |
| ::SysFreeString(str_stock); | |
| } | |
| void DoEnterMonitor() | |
| { | |
| SKCOM->SKQuoteLibPtr->SKQuoteLib_EnterMonitor(); | |
| } | |
| }; | |
| void DoJob(StockBot& Bot, Job& j) | |
| { | |
| switch (j.do_type) | |
| { | |
| case Job::Quote_Connect: | |
| Bot.SKQuoteLibOnConnection(j.nValue1, j.nValue2); | |
| break; | |
| case Job::Quote_EnterMonitor: | |
| Bot.DoEnterMonitor(); | |
| break; | |
| case Job::GetStockByIndex: | |
| Bot.DoGetStockByIndex(); | |
| break; | |
| case Job::GetStockByIndexResult: | |
| Bot.DoOnNotifyQuote(j.nValue1, j.nValue2); | |
| break; | |
| case Job::OnNotifyQuote: | |
| Bot.Stock[j.Stock->bstrStockNo] = j.Stock; | |
| printf("OnNotifyQuote : %d %ld\n", j.Stock->sStockIdx, j.Stock->nClose); | |
| break; | |
| } | |
| } | |
| int main() | |
| { | |
| CoInitializeEx(NULL, COINIT_MULTITHREADED); | |
| HRESULT hr; | |
| StockBot Bot("6111"); | |
| Bot.DoLogin("帳號", "密碼"); | |
| while (true) | |
| { | |
| while (!q.empty()) { | |
| Job j = q.dequeue(); | |
| DoJob(Bot, j); | |
| } | |
| Sleep(100); | |
| } | |
| CoUninitialize(); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment