How to inform data-changed in static function?
-
I have suffered from some trouble for a long time when I used hiredis in my app.
In order to get server response, I have to write a static function as a callback function. In the function, I change some data and emit signal to inform my main thread to update display.
The question is the emit signal must be static in callback function, but I couldn't use signal&slot(connect) when I declare the signal static.So how to inform outside in static function? -
hi @Bayesky
take look at his rather old thread
https://forum.qt.io/topic/87302/sending-static-signals-is-it-possible/5the possible solution, the one from @VRonin with the big warning, may be of use.
-
Actually there is a much cleaner solution. Say the static callback function must have signature
void callBackFunction(int argument);
then you declare a static functionvoid fullCallBack(int argument, MyObject* emitter){ emitter->mySignal(argument); }
and then use
std::bind
to create a function that matches the required signature:MyObject* object = new MyObject; server->sendSomething("hello world",std::bind(fullCallBack,std::placeholders::_1,object));
-
@VRonin Thank you very much.
I have define a static function with 4 parametersvoid Widget::fullCallBack(redisAsyncContext *c, void *r, void *priv, Widget* emitter){ //print something and get some values emitter->mySignal(); //emit signal }
And then I use the following codes to shrink parameters to 3.
Widget *w = new Widget; std::function<void(redisAsyncContext *c, void *r, void *priv)> fun2; fun2 = std::bind(fullCallBack, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, w);
When I use
fun2
to replacesubCallback
,redisAsyncCommand(c, fun2, (char*) "sub"*, "SUBSCRIBE foo");//send SUB command
an error occur which said:
Widget.cpp:43:5: error: no matching function for call to 'redisAsyncCommand' async.h:132:5: note: candidate function not viable: no known conversion from 'std::function<void (redisAsyncContext *, void *, void *)>' (aka 'function<void (redisAsyncContext *, void *, void *)>') to 'redisCallbackFn *' (aka 'void (*)(struct redisAsyncContext *, void *, void *)') for 2nd argument
Are there any mistakes in use? Thank you.
-
@VRonin Yes, it is a C function.
int redisAsyncCommand( redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, ...);
The function
redisAsyncConnect
can be used to establish a non-blocking connection to Redis. It returns a pointer to the newly createdredisAsyncContext
struct.
Theprivdata
argument can be used to curry arbitrary data to the callback from the point where the command is initially queued for execution. -
EDIT: See @SGaist answer below for the correct solution
Yeah, the problem is that C doesn't do objects (aka functors) unfortunately. You'll have to do something ugly, declare a static
Widget* emitter;
andvoid fullCallBack(redisAsyncContext *c, void *r, void *priv){ //print something and get some values emitter->mySignal(); //emit signal }
then you can use
emitter=w; redisAsyncCommand(c, fullCallBack, (char*) "sub"*, "SUBSCRIBE foo");
It looks super ugly in C++ but you need to adapt the style to what C can handle
-
@VRonin I attempt to use a
static Widget* emitter;
as a private variable. And thenvoid fullCallBack(redisAsyncContext *c, void *r, void *priv){ //print something and get some values //no matter declare emitter = new Widget; or not emitter->mySignal(); //emit signal }
Another error occur which says
:-1: error: symbol(s) not found for architecture x86_64 :-1: error: linker command failed with exit code 1 (use -v to see invocation)
-