Skip to content

Instantly share code, notes, and snippets.

@kwedr
Last active July 6, 2017 08:10
Show Gist options
  • Select an option

  • Save kwedr/9a862582a016319949e63eca8b013428 to your computer and use it in GitHub Desktop.

Select an option

Save kwedr/9a862582a016319949e63eca8b013428 to your computer and use it in GitHub Desktop.
群益API with cpp
#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