0

To illustrate the question, let's imagine a dummy example where we have this function from an external API:

// This function is run in a separated thread
void Transfert(string source, string destination, void (*callbackFunction)(int))
{
    for(int i = 0; i < 100; i++)
    {
        // Simulation of a file transfert
        // ...
        // 

        // We call the callback function to update the progression of the file transfert
        callbackFunction(i);
    }
}

I want to use this function to transfert a file and follow the progress with the help of the callback function. Here is my code:

// Class containing information about the transfert
class FileTransfert
{
public:
    FileTransfert(string, string);
    void MyCallback(int);

    // Those members are public to simplify this example but should be private
    long m_progress;
    string m_source;
    string m_destination;
};

FileTransfert::FileTransfert(string source, string destination)
{
    m_source = source;
    m_destination = destination;
}

// Used to update the progress variable
void FileTransfert::MyCallback(int progress)
{
    m_progress = progress;
}

int main(int argc, char* argv[])
{
    FileTransfert f("source.txt", "destination.txt");

    // It's a new thread
    Transfert(f.m_source, f.m_destination, f.MyCallback); // Compilation error

    // Now I want to follow the transfer with the m_progress variable

    return 0;
}

My class FileTransfert has a m_progress member and I would like to refresh it during the file transfert. So I create a callback function who updates m_progress. The problem is I cannot use a method of an object as a callback function.

So, here is my question : how can I modify my code to follow the progression of the transfert?
I have some constraints : I have to call Transfert from a function who is outside the FileTransfert class and the m_progress variable has to be inside the FileTransfert class. In other words, I can't change all the architecture of my code.

Important note: I can't change the code and the signature of the Transfert function. In the answers of those two questions (here and here), we change the signature of the function but I can't in my case.


EDIT

As I said in comments, there is no proper solution to this problem if I can't change the signature of the Transfert function. One idea is to use global variables but it can be very risky in a multithread environment.

Pierre
  • 1,942
  • 3
  • 23
  • 43
  • Here you go, https://stackoverflow.com/a/14189561/451600 – Captain Giraffe Jul 11 '18 at 15:59
  • @CoryKramer The answers on your dupe are quite dated. – Captain Giraffe Jul 11 '18 at 16:01
  • @CaptainGiraffe In your post, the user can modify the `addHandler` signature. In my case, I cannot change the `Transfert` signature and I cannot use `std::function`. – Pierre Jul 11 '18 at 16:26
  • 1
    `std::bind(FileTransfert::MyCallBack, this, _1)` should do the trick. The `_1` is a placeholder for the int. – Captain Giraffe Jul 11 '18 at 16:35
  • @CaptainGiraffe It only works if I change the signature of `Transfert` by `void Transfert(string source, string destination, function callbackFunction)` which I can't do. If I don't, I get a C2664 error : impossible to convert `std::tr1::_Bind<_Result_type,_Ret,_BindN>` into `void (__cdecl *)(int)`. – Pierre Jul 11 '18 at 16:50
  • Indeed. I didn't realize you couldn't change that. – Captain Giraffe Jul 11 '18 at 19:14
  • According to this exchange I had on the chatroom, if I can't modify the signature of the `Transfert` function, I can't give to it the state of my `FileTransfert` object to update its `m_nProgress` member : https://chat.stackoverflow.com/transcript/message/43247116#43247116 – Pierre Jul 13 '18 at 15:02

0 Answers0