yes, .it works well.
yes, .it works well.
of course,the following is code.but i still cannot decalre the static variable in class scope,when i do it ,the VC7 always report various error.either not define the variable or cannot be interped by metaobject.
Qt Code:
///////////////////////storescpThread.h typedef (*STORESCPCALLBACK)(void *callbackData, char* statusDetail); static unsigned long classAddress; { Q_OBJECT public: ~storescpThread(); protected: void run(); static void emitMsg( unsigned long user_value,char * filename) { storescpThread* pthis = (storescpThread*)user_value; // pthis->setText(state,filename); } void mycallback(); private : QTextEdit * textEdit; static void storeSCPCallback(void *callbackData, char* statusDetail); void setText(char * state,char * name); }; ///////////////////////storeScpThread.cpp { textEdit=txtEdit; classAddress =(unsigned long)this ; } void storescpThread:: storeSCPCallback(void *callbackData, char* statusDetail) { emitMsg(classAddress,statusDetail); return ; } void storescpThread::mycallback() { myThirdCallFunction(storeSCPCallback); //the third party function, which used callback as param }To copy to clipboard, switch view to plain text mode
Oh God.... This is some kind of madness... I won't even ask what happens if you have two instances of the thread class or what happens if you delete the object without unregistering the callback...
Why don't you move the callback method outside the class so that it's a standalone function instead? You can't call any of the nonstatic class member anyway, so what's the point of having this static method part of the thread class?
Implementing some Win32 Callback is quite necessary in some cases to make *good* use of Win32 API.
Found this old thread on google. What I did is to add a global pointer to the current class, like this:
in the header file
Qt Code:
class MyClass { public: MyClass (); ~MyClass (); private: static void CALLBACK MyCallback (int nMsg); void emitMySignal (int nMsg); signals: mySignal (int nMsg); }To copy to clipboard, switch view to plain text mode
in the cpp file, at the beginning define a global pointer to the current class
Qt Code:
MyClass* pThis; MyClass:MyClass () { pThis = this; } void MyClass::MyCallback (int nMsg) { pThis->emitMySignal(nMsg); } void MyClass::emitMySignal (int nMsg) { emit mySignal (nMsg); }To copy to clipboard, switch view to plain text mode
I had a very similar situation with the libusb library. If I wanted to have callbacks and use the async model they have laid out I couldn't figure out a better way.
Is this the best way still, at least when using existing c libraries?
In my experience with callbacks from various libraries, there's usually a method for storing a pointer or user data that is presented to the callback. I've used that capability in the past to pass a pointer to the class instance, so that even though the static member callback function doesn't have a "this" pointer, the method would be able to execute any class functions or class data, etc.
Last edited by anda_skoa; 7th July 2016 at 17:22.
I write the best type of code possible, code that I want to write, not code that someone tells me to write!
Easier to give you an example. Here's what I've used for libCurl when I've used its callback functions.
header file that declares the static member function:
cpp file that implements the static member functiion:Qt Code:
private: static size_t write_function( void *ptr, size_t size, size_t nmemb, void *stream);To copy to clipboard, switch view to plain text mode
and finally the cpp code that invokes libcurl, specifies the callback, and sets the user data pointer, etc:Qt Code:
size_t libFlickr::write_function( void *ptr, size_t size, size_t nmemb, void *stream) { size_t total = size * nmemb; libFlickr* pFlickr = reinterpret_cast<libFlickr*>(stream); if (pFlickr) { pFlickr->some_public_method(); return total; } else { return 0; } }To copy to clipboard, switch view to plain text mode
In the case of libcurl, it passes the CURLOPT_WRITEDATA value to the callback function as the void* stream argument. Every other use I've had for callback functions has provided a way to pass data that is given back to the callback function, so passing the "this" pointer results in the callback receiving the instance pointer.Qt Code:
m_code = curl_easy_setopt(m_pCurl, CURLOPT_WRITEFUNCTION, libFlickr::write_function); m_code = curl_easy_setopt(m_pCurl, CURLOPT_WRITEDATA, (void*)this); m_code = curl_easy_perform(m_pCurl);To copy to clipboard, switch view to plain text mode
Hope that helps.
I write the best type of code possible, code that I want to write, not code that someone tells me to write!
Goddard (7th July 2016)
jefftee (7th July 2016)
Last edited by jefftee; 7th July 2016 at 16:29.
I write the best type of code possible, code that I want to write, not code that someone tells me to write!
Strange, I edited it for you.
Cheers,
_
jefftee (8th July 2016)
Good stuff. I'm just learning working with this type of library. Appreciate that. I now noticed it does indeed offer a void* user_data parameter in the function to pass through. I just overlooked that completely.
Bookmarks