Search code examples
c++indyrad-studio

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


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

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

//AThread->Connection->WriteBuffer(&Pkt,sizeof(BKUK_PACKET),1);

----------(Omission)---------------------------------------
}

The function named WriteBuffer() 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 the TIdIOHandler.Write(TIdBytes) method when I was looking at the instruction manual for Indy 10.

I referred to the code that I told you before:

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

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

----------(Omission)---------------------------------------

Populate02(&Pkt,AContext->Connection->IOHandler);
}

But when I tried to program as above, I get an error:

[bcc32c error] Main.cpp(608): no matching function for call to 'Populate02'

Main.cpp(478): candidate function [with T = _BKUK_PACKET_ *] not viable: no known conversion from '_PACKET *' (aka '_BKUK_PACKET_ *') to '_BKUK_PACKET_ *&' for 1st argument

Please tell me how to fix this code.


Solution

  • You are not calling PopulateWriteBuffer() at all, you are calling some other function named Populate02() instead. Assuming that is just a typo and you really meant PopulateWriteBuffer(), you are passing it a pointer to a BKUK_PACKET but it takes a reference to a BKUK_PACKET instead.

    Change

    Populate02(&Pkt, AContext->Connection->IOHandler);
    

    To

    PopulateWriteBuffer(Pkt, AContext->Connection->IOHandler);
    

    That being said, the TIdIOHandler::Write(TIdBytes) method will work just fine, you just need to copy your BKUK_PACKET variable into an intermediate TIdBytes variable first, such as with Indy's RawToBytes() function, eg:

    void __fastcall TfrmMain::ServerConnect(TIdContext *AContext)
    {
        BKUK_PACKET Pkt;
        // populate Pkt as needed...
    
        AContext->Connection->IOHandler->Write(RawToBytes(&Pkt, sizeof(BKUK_PACKET)));
    }
    

    Alternatively, you can use the TIdIOHandler::Write(TStream*) method with a TIdMemoryBufferStream to send directly from your BKUK_PACKET variable without making a copy of its data first, similar to Indy 9's WriteBuffer(), eg:

    #include <memory>
    
    void __fastcall TfrmMain::ServerConnect(TIdContext *AContext)
    {
        BKUK_PACKET Pkt;
        // populate Pkt as needed...
    
        std::unique_ptr<TIdMemoryBufferStream> strm(new TIdMemoryBufferStream(&Pkt, sizeof(BKUK_PACKET)));
        // or std::auto_ptr prior to C++11...
    
        AContext->Connection->IOHandler->Write(strm.get());
    }