Interactive Brokers C++ Ошибка: ошибка: 'min' не был объявлен в этой области

Я пытаюсь настроить Interactive Brokers API в Ubuntu (18.04) . Я установил как IB Gateway, который используется для связи с биржами, так и другое программное обеспечение API для разработки торговых алгоритмов на Java, C++, C# и Python. (Вы можете найти здесь). API написан как на Java, так и на C++, и, как было сказано ранее, поддерживает оба языка. Однако при попытке скомпилировать пример из их исходного кода возникает ошибка в файле EReader.cpp. Я имел дело с несколькими другими ошибками C++ в их коде, но эту я не могу понять. Вот код:

#include "StdAfx.h"
#include "shared_ptr.h"
#include "Contract.h"
#include "EDecoder.h"
#include "EMutex.h"
#include "EReader.h"
#include "EClientSocket.h"
#include "EPosixClientSocketPlatform.h"
#include "EReaderSignal.h"
#include "EMessage.h"
#include "DefaultEWrapper.h"

#define IN_BUF_SIZE_DEFAULT 8192

static DefaultEWrapper defaultWrapper;

EReader::EReader(EClientSocket *clientSocket, EReaderSignal *signal)
: processMsgsDecoder_(clientSocket->EClient::serverVersion(), clientSocket->getWrapper(), clientSocket) {
    m_isAlive = true;
    m_pClientSocket = clientSocket;       
    m_pEReaderSignal = signal;
    m_needsWriteSelect = false;
    m_nMaxBufSize = IN_BUF_SIZE_DEFAULT;
    m_buf.reserve(IN_BUF_SIZE_DEFAULT);
}

EReader::~EReader(void) {
m_isAlive = false;

#if defined(IB_WIN32)
WaitForSingleObject(m_hReadThread, INFINITE);
#endif
}

void EReader::checkClient() {
m_needsWriteSelect = !m_pClientSocket->getTransport()- 
isOutBufferEmpty();
}

void EReader::start() {
#if defined(IB_POSIX)
pthread_t thread;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create( &thread, &attr, readToQueueThread, this );
pthread_attr_destroy(&attr);
#elif defined(IB_WIN32)
m_hReadThread = CreateThread(0, 0, readToQueueThread, this, 0, 0);
#else
#   error "Not implemented on this platform"
#endif
}

#if defined(IB_POSIX)
void * EReader::readToQueueThread(void * lpParam)
#elif defined(IB_WIN32)
DWORD WINAPI EReader::readToQueueThread(LPVOID lpParam)
#else
#   error "Not implemented on this platform"
#endif
{
EReader *pThis = reinterpret_cast<EReader *>(lpParam);

pThis->readToQueue();
return 0;
}

void EReader::readToQueue() {
EMessage *msg = 0;

while (m_isAlive) {
    if (m_buf.size() == 0 && !processNonBlockingSelect() && m_pClientSocket->isSocketOK())
        continue;

    if (!putMessageToQueue())
        break;
}

m_pClientSocket->handleSocketError();
m_pEReaderSignal->issueSignal(); //letting client know that socket was closed
}

bool EReader::putMessageToQueue() {
EMessage *msg = 0;

if (m_pClientSocket->isSocketOK())
    msg = readSingleMsg();

if (msg == 0)
    return false;

m_csMsgQueue.Enter();
m_msgQueue.push_back(ibapi::shared_ptr<EMessage>(msg));
m_csMsgQueue.Leave();
m_pEReaderSignal->issueSignal();

return true;
}

bool EReader::processNonBlockingSelect() {
fd_set readSet, writeSet, errorSet;
struct timeval tval;

tval.tv_usec = 100 * 1000; //100 ms
tval.tv_sec = 0;

if( m_pClientSocket->fd() >= 0 ) {

    FD_ZERO( &readSet);
    errorSet = writeSet = readSet;

    FD_SET( m_pClientSocket->fd(), &readSet);

    if (m_needsWriteSelect)
        FD_SET( m_pClientSocket->fd(), &writeSet);

    FD_SET( m_pClientSocket->fd(), &errorSet);

    int ret = select( m_pClientSocket->fd() + 1, &readSet, &writeSet, &errorSet, &tval);

    if( ret == 0) { // timeout
        return false;
    }

    if( ret < 0) {  // error
        m_pClientSocket->eDisconnect();
        return false;
    }

    if( m_pClientSocket->fd() < 0)
        return false;

    if( FD_ISSET( m_pClientSocket->fd(), &errorSet)) {
        // error on socket
        m_pClientSocket->onError();
    }

    if( m_pClientSocket->fd() < 0)
        return false;

    if( FD_ISSET( m_pClientSocket->fd(), &writeSet)) {
        // socket is ready for writing
        onSend();
    }

    if( m_pClientSocket->fd() < 0)
        return false;

    if( FD_ISSET( m_pClientSocket->fd(), &readSet)) {
        // socket is ready for reading
        onReceive();
    }

    return true;
}

return false;
}

void EReader::onSend() {
m_pEReaderSignal->issueSignal();
}

void EReader::onReceive() {
int nOffset = m_buf.size();

m_buf.resize(m_nMaxBufSize);

int nRes = m_pClientSocket->receive(m_buf.data() + nOffset, m_buf.size() - nOffset);

if (nRes <= 0)
    return;

m_buf.resize(nRes + nOffset);   
}

bool EReader::bufferedRead(char *buf, int size) {
while (size > 0) {
    while (m_buf.size() < size && m_buf.size() < m_nMaxBufSize)
        if (!processNonBlockingSelect() && !m_pClientSocket->isSocketOK())
            return false;

    int nBytes = (std::min<unsigned int>)(m_nMaxBufSize, size);



    std::copy(m_buf.begin(), m_buf.begin() + nBytes, buf);
    std::copy(m_buf.begin() + nBytes, m_buf.end(), m_buf.begin());
    m_buf.resize(m_buf.size() - nBytes);

    size -= nBytes;
    buf += nBytes;
}

return true;
}

EMessage * EReader::readSingleMsg() {
if (m_pClientSocket->usingV100Plus()) {
    int msgSize;

    if (!bufferedRead((char *)&msgSize, sizeof(msgSize)))
        return 0;

    msgSize = htonl(msgSize);

    if (msgSize <= 0 || msgSize > MAX_MSG_LEN)
        return 0;

    std::vector<char> buf = std::vector<char>(msgSize);

    if (!bufferedRead(buf.data(), buf.size()))
        return 0;

    return new EMessage(buf);
}
else {
    const char *pBegin = 0;
    const char *pEnd = 0;
    int msgSize = 0;

    while (msgSize == 0)
    {
        if (m_buf.size() >= m_nMaxBufSize * 3/4) 
            m_nMaxBufSize *= 2;

        if (!processNonBlockingSelect() && !m_pClientSocket->isSocketOK())
            return 0;

        pBegin = m_buf.data();
        pEnd = pBegin + m_buf.size();
        msgSize = EDecoder(m_pClientSocket->EClient::serverVersion(), &defaultWrapper).parseAndProcessMsg(pBegin, pEnd);
    }

    std::vector<char> msgData(msgSize);

    if (!bufferedRead(msgData.data(), msgSize))
        return 0;

    if (m_buf.size() < IN_BUF_SIZE_DEFAULT && m_buf.capacity() > IN_BUF_SIZE_DEFAULT)
    {
        m_buf.resize(m_nMaxBufSize = IN_BUF_SIZE_DEFAULT);
        m_buf.shrink_to_fit();
    }

    EMessage * msg = new EMessage(msgData);

    return msg;
}
}

ibapi::shared_ptr<EMessage> EReader::getMsg(void) {
m_csMsgQueue.Enter();

if (m_msgQueue.size() == 0) {
    m_csMsgQueue.Leave();

    return ibapi::shared_ptr<EMessage>();
}

ibapi::shared_ptr<EMessage> msg = m_msgQueue.front();

m_msgQueue.pop_front();
m_csMsgQueue.Leave();

return msg;
}


void EReader::processMsgs(void) {
m_pClientSocket->onSend();
checkClient();

ibapi::shared_ptr<EMessage> msg = getMsg();

if (!msg.get())
    return;

const char *pBegin = msg->begin();

while (processMsgsDecoder_.parseAndProcessMsg(pBegin, msg->end()) > 0) 
{
    msg = getMsg();

    if (!msg.get())
        break;

    pBegin = msg->begin();
} 
}

Я получаю следующую ошибку: ошибка

error: 'min' was not declared in this scope  int nBytes = 
min(m_nMaxBuffSize, size);

Мне приходилось делать другие вещи, такие как редактирование другого исходного кода и make-файлов, я застрял здесь. Любое понимание будет оценено.


person ofey73    schedule 23.07.2018    source источник


Ответы (1)


В моем источнике версии 973 в этой строке у меня есть

int nBytes = (std::min<unsigned int>)(m_nMaxBufSize, size);

Убедитесь, что вы используете последнюю версию. Проблема может быть примером того, что происходит здесь Почему использование пространства имен std считается плохой практикой?

person brian    schedule 23.07.2018
comment
Однако теперь процесс компиляции пошел дальше, но застрял на невозможности найти заголовочный файл в Main.cpp. Не удалось найти файл Windows.h, и он был включен в основной, я не могу найти Windows.h нигде в каталоге со всеми материалами IBKR. Вы сталкивались с этой проблемой при настройке? - person ofey73; 24.07.2018
comment
Я не использовал C++, и вы не должны. Я не отрицал ваш вопрос, но кто-то сделал это, поскольку это была очевидная ошибка для любого программиста на C++. Кроме того, windows.h — это очень простой заголовочный файл, который необходим каждой программе Windows. Я могу только заключить, что это ваша первая программа на C++, и ваша среда сборки настроена неправильно. Ваш первый проект на C++ не должен включать все ваши деньги! Если вы знакомы с java или python, попробуйте их. На C++ API всегда жаловались другие, у которых было гораздо больше опыта. - person brian; 24.07.2018
comment
Да, там определенно много чего не так. Даже такие очевидные вещи, как регистры (да, верхний и нижний регистр) с путями и каталогами (например, ../../../source/cppclient vs ../../../source/CppClient). До того, как я зашел в make-файл и изменил его, он не компилировался (ага). Да, я новичок в C++ (хотя это не моя первая программа). Я бы сказал, что хорошо разбираюсь в C, Python и R. Спасибо. - person ofey73; 24.07.2018
comment
И если для него требуется заголовок Windows.h, может ли он быть собран исключительно в Windows? - person ofey73; 24.07.2018
comment
Вы можете поискать, как использовать MinGW для кросс-компиляции для окон в Linux. Это будет файл windows.h. - person brian; 24.07.2018
comment
если честно, Java API тоже не выглядит слишком крутым. Например, в файле ApiDemo.java они возвращают список массивов, а не список. Кроме того, INSTANCE является конечным константным, а не изменяемым экземпляром, не знаю, почему все переменные являются окончательными, вызов static register() тоже довольно глупый... почему бы не вызвать init() для ясности? В нем есть переменные-члены, инициализирующие друг друга, что может быть проблематично. На самом деле выглядит очень плохо. - person ofey73; 02.08.2018
comment
Лично я бы не стал использовать способ ApiDemo для создания программы. Вы можете видеть, что он использует странные классы ib.controller. Программа TestJavaClient намного проще IMO. Я всегда импортирую только com.ib.client.* для своих программ. - person brian; 03.08.2018