问题
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