cURL / Mailing Lists / curl-library / Single Mail

curl-library

Re: red:call back funcitons

From: Stephen Collyer <scollyer_at_netspinner.co.uk>
Date: Thu, 03 Jul 2008 11:50:36 +0100

nagarajan.sreenivasan_at_wipro.com wrote:
> Hi
> A query regarding call back funcitons my_fwrite and read_callback . I
> want to have these 2 fucntions as member functions of a class and
>
> use it for object specific.I dont want to have them static. as they are
> not thread safe.Is it not possible. I need this kind of scenario to make
> it some thing like thread safe so that parallel
>
> connections, dont have a chance of breaking it. please advice on this.

Yes, this is possible. I have done it successfully.

Essentially, you need to produce a function pointer object
which binds the member function to a specific object.

I use the Boost function class for this, like so:

> typedef struct
> {
> double bytes_to_transfer;
> double bytes_transferred;
> }
> ProgressData;
>
> typedef boost::function<bool (ProgressData)> ProgressCallback;

That defines a function object taking a single ProgressData
arg, and that's used to pass curl callback info into your member
function.

You must then, at run time, produce the appropriate function pointer
callback by binding the member function to the current object, like so:

> ProgressCallback cb =
> std::bind1st(std::mem_fun(&FileTransferScheduler::progress_callback),
> this);
>

To call this from curl, I do the following:

> curl_easy_setopt(curl_, CURLOPT_PROGRESSFUNCTION, download_progress_callback);
> curl_easy_setopt(curl_, CURLOPT_PROGRESSDATA, &progress_cb_);

This makes curl callback to a function with C linkage and to
pass it an opaque ProgressCallBack* which we earlier set up to
store the function pointer that we bound (i.e. progress_cb_
was set to the cb variable shown above)

download_progress_callback then does the following:

> int download_progress_callback(ProgressCallback *mdp_progress_cb,
> double bytes_to_download,
> double bytes_downloaded,
> double bytes_to_upload,
> double bytes_uploaded)
> {
> // return 0 to allow transfer to continue
>
> ProgressData current_data;
> current_data.bytes_to_transfer = bytes_to_download;
> current_data.bytes_transferred = bytes_downloaded;
>
> // call the callback if we have one
>
> if (mdp_progress_cb && ! (*mdp_progress_cb)(current_data))
> {
> return 1;
> }
>
> return 0;
> }

i.e. it packages up curl's callback info into the ProgressData struct
that are bound member function expects, cand calls it (if it's set).

-- 
Regards
Steve Collyer
Netspinner Ltd
Received on 2008-07-03