简体   繁体   中英

How can I use a member function pointer in libcurl

I am using libcurl I have my downloading of files inside of a class, to which I want to see a progress function. I notice I can set a typical function pointer by

curl_easy_setopt(mCurl, CURLOPT_PROGRESSFUNCTION, progress_func3);

However, I would like to set it to a function pointer to my class. I can get the code to compile with

curl_easy_setopt(mCurl, CURLOPT_PROGRESSFUNCTION, &MyClass::progress_func3);

and the progress_func3 function will get called. The problem is, as soon as it returns there will be a "Buffer overrun detected!" error through, saying the program can not safely continue and execute, and must be terminated. (It is a Microsoft Visual C++ Runtime Library error window, I am using Visual Studio 2010).

When I use a function, there is no problem, but when I use a member function pointer, I will get this error. How can I use a member function pointer in libcurl?

A non-static member function needs a this pointer to be callable. You can't provide that this pointer with this type of interface, so using a non-static member function is not possible.

You should create a "plain C" function as your callback, and have that function call the member function on the appropriate MyClass instance.

Try something like:

int my_progress_func(void *clientp, ...)
{
   MyClass *mc = static_cast<MyClass*>(clientp);
   mc->your_function(...);
   return 0; // or something else
}

Then:

curl_easy_setopt(mCurl, CURLOPT_PROGRESSDATA,     &your_myclass_object);
curl_easy_setopt(mCurl, CURLOPT_PROGRESSFUNCTION, my_progress_func);

(You're responsible for the type match here, obviously. If you attach anything else but a MyClass pointer to the progress data, you're on your own.)

You can this using boost::bind(). For example:

boost::bind(&MyClass::progress_func3, this);

is a pointer to a method that returns void and has no arguments. If your callback needs arguments, use placeholders as follows:

boost::bind(&MyClass::progress_func3, this, _1, _2) 

The this pointer can be replaced with a point to an instance of MyClass .

EDIT: You should be able to use boost::function<> and function ptr types relatively interchangeable. For example:

typedef boost::function< void (int, short) > Callback;

is equivalent to

typedef void (Callback)(int);

You may have to layer it with a function in between to make the compiler happy. I know that I've defined a callback using boost::function<> and passed in a regular function pointer.

Class instance 'this' works:

static int progressCallback( void * p, double dltotal, double dlnow, double ultotal, double ulnow )
{
    QTWindow * w{ static_cast< QTWindow * >( p ) };
    emit w->uploadProgressData( ulnow, ultotal );
    return 0;
}

curl_easy_setopt( curl, CURLOPT_NOPROGRESS, 0L );
curl_easy_setopt( curl, CURLOPT_PROGRESSFUNCTION, progressCallback );
curl_easy_setopt( curl, CURLOPT_PROGRESSDATA, this );

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM