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

戏子无情 提交于 2019-12-25 17:14:29

问题


This code is written in Borland C++Builder 6 using Indy 9:

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

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

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

The function named ReadBuffer() is not found in Indy 10. Is there an equivalent function?

BKUK_PACKET is a structure of about 1200 bytes.

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

I found ReadBytes() when I was looking at the instruction manual for Indy 10. But when I tried to program as below, I get an error:

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

Please tell me how to fix this code.


回答1:


The signature of ReadBytes() is

virtual void __fastcall ReadBytes(Idglobal::TIdBytes &VBuffer, 
                                  int AByteCount,
                                  bool AAppend = true);

TIdBytes dynamic nature makes ReadBytes() not a good choice if you want to populate Pkt without using an intermediate variable.

You could however use TIdIOHandler's

System::Byte __fastcall ReadByte();

and create your own function to populate objects:

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();
}

and use it like this:

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



回答2:


The TIdIOHandler::ReadBytes() method will work just fine, you just need to use an intermediate TIdBytes variable to read into first, and then you can copy that data into your BKUK_PACKET variable, such as with Indy's BytesToRaw() function, eg:

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...
}

Alternatively, you can use the TIdIOHandler::ReadStream() method with a TIdMemoryBufferStream to read directly into your BKUK_PACKET variable, similar to Indy 9's ReadBuffer(), eg:

#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...
}


来源:https://stackoverflow.com/questions/59125361/is-there-an-equivalent-of-indy-9s-readbuffer-in-indy-10

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!