Indy 10 中是否有与 Indy 9 的 ReadBuffer() 等效的东西?

Is there an equivalent of Indy 9's ReadBuffer() in Indy 10?

此代码是使用 Indy 9 在 Borland C++Builder 6 中编写的:

void __fastcall TfrmMain::ServerConnect(TIdPeerThread *AThread)
{
     BKUK_PACKET Pkt;
----------(中略)---------------------------------------

AThread->Connection->ReadBuffer((BYTE *)&Pkt,sizeof(BKUK_PACKET));

----------(中略)---------------------------------------
}

在 Indy 10 中找不到名为 ReadBuffer() 的函数。是否有等效函数?

BKUK_PACKET是一个1200字节左右的结构

typedef struct _BKUK_PACKET_
{
    BYTE head[4];
    WORD PayLoad;
    WORD Length;
    BYTE Data[1200];
    WORD Ver;
    BYTE tail[2];
}BKUK_PACKET;

我在查看 Indy 10 的说明手册时发现 ReadBytes()。但是当我尝试如下编程时,出现错误:

Context->Connection->IOHandler->ReadBytes((BYTE *)&Pkt,sizeof(BKUK_PACKET))

[bcc32c error] Main.cpp(530): non-const lvalue reference to type 'Idglobal::TIdBytes' (aka 'DynamicArray<unsigned char>') cannot bind to a temporary of type 'BYTE *' (aka 'unsigned char *')

IdIOHandler.hpp(235): passing argument to parameter 'VBuffer' here

请告诉我如何修复此代码。

ReadBytes()的签名是

virtual void __fastcall ReadBytes(Idglobal::TIdBytes &VBuffer, 
                                  int AByteCount,
                                  bool AAppend = true);
如果您想在不使用中间变量的情况下填充 Pkt

TIdBytes 动态特性使得 ReadBytes() 不是一个好的选择。

但是您可以使用 TIdIOHandler

System::Byte __fastcall ReadByte();

并创建您自己的函数来填充对象:

template<typename T>
void __fastcall Populate(T& obj, TIdIOHandler* ioh) {
    System::Byte* p = (System::Byte*) &obj;
    for(unsigned count=0; count<sizeof(T); ++count, ++p)
        *p = ioh->ReadByte();
}

并像这样使用它:

BKUK_PACKET Pkt;
Populate(Pkt, Context->Connection->IOHandler);

TIdIOHandler::ReadBytes()方法就可以了,你只需要先使用一个中间TIdBytes变量读入,然后你就可以将该数据复制到你的BKUK_PACKET变量中, 比如 Indy 的 BytesToRaw() 函数, 例如:

void __fastcall TfrmMain::ServerConnect(TIdContext *AContext)
{
    BKUK_PACKET Pkt;

    TIdBytes bytes;
    AContext->Connection->IOHandler->ReadBytes(bytes, sizeof(BKUK_PACKET));
    BytesToRaw(bytes, &Pkt, sizeof(BKUK_PACKET));

    // use Pkt as needed...
}

或者,您可以使用带有 TIdMemoryBufferStreamTIdIOHandler::ReadStream() 方法直接读入您的 BKUK_PACKET 变量,类似于 Indy 9 的 ReadBuffer(),例如:

#include <memory>

void __fastcall TfrmMain::ServerConnect(TIdContext *AContext)
{
    BKUK_PACKET Pkt;

    std::unique_ptr<TIdMemoryBufferStream> strm(new TIdMemoryBufferStream(&Pkt, sizeof(BKUK_PACKET)));
    // or std::auto_ptr prior to C++11...
    AContext->Connection->IOHandler->ReadStream(strm.get(), sizeof(BKUK_PACKET), false);

    // use Pkt as needed...
}