Skip to content

Commit 5579a6a

Browse files
Merge pull request #1362 from redis/DOC-4997-hiredis-qt-example
DOC-4997 hiredis async API and integration examples
2 parents 1475cab + 22190c9 commit 5579a6a

File tree

6 files changed

+689
-12
lines changed

6 files changed

+689
-12
lines changed

content/develop/clients/hiredis/_index.md

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@ Then, in a terminal, go into the `hiredis` folder and run the `make` command to
3030
the dynamically-loaded library for `hiredis` (this has the name `libhiredis.dylib` on
3131
MacOS and `libhiredis.so` on Linux). You can copy this library to your
3232
project folder or run `sudo make install` to install it to `/usr/local/lib`.
33-
You should also copy the header files `hiredis.h`, `alloc.h`, `read.h`, and
34-
`sds.h` to your project.
3533

3634
## Connect and test
3735

@@ -43,7 +41,7 @@ connection. An explanation of the code follows the example.
4341
```c
4442
#include <stdio.h>
4543

46-
#include "hiredis.h"
44+
#include <hiredis/hiredis.h>
4745

4846
int main() {
4947
// The `redisContext` type represents the connection
@@ -81,8 +79,9 @@ int main() {
8179

8280
For a real project, you would build your code with a makefile, but for
8381
this simple test, you can just place it in a file called `main.c` and
84-
build it with the following command (assuming you used `make install` to
85-
install the `libhiredis` library):
82+
build it with the following command. (If you didn't install `hiredis`
83+
using `make install`, then you should also use the `-I` option to
84+
specify the folder that contains the `hiredis` headers.)
8685

8786
```bash
8887
cc main.c -L/usr/local/lib -lhiredis
@@ -123,11 +122,7 @@ to prevent errors.
123122
The [`hiredis`](https://github.com/redis/hiredis) Github repository contains
124123
examples and details that may be useful if you are using `hiredis` to
125124
implement a higher-level client for another programming language. There are
126-
also examples showing how to use `hiredis` from a
127-
[C++ application](https://github.com/redis/hiredis/blob/master/examples/example-qt.cpp)
128-
created with [Qt](https://www.qt.io/) and how to use the
129-
[asynchronous API](https://github.com/redis/hiredis?tab=readme-ov-file#asynchronous-api)
130-
with the [libev](https://software.schmorp.de/pkg/libev.html) and
131-
[libevent](https://libevent.org/) libraries.
125+
also examples showing how to use `hiredis` adapter headers to integrate with
126+
various event handling frameworks.
132127

133128
See the other pages in this section for more information and examples.

content/develop/clients/hiredis/connect.md

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ and port as its arguments, and returns a context object.
2525
```c
2626
#include <stdio.h>
2727

28-
#include "hiredis.h"
28+
#include <hiredis/hiredis.h>
2929
.
3030
.
3131
.
@@ -62,4 +62,84 @@ freeReplyObject(reply);
6262
redisFree(c);
6363
```
6464
65+
## Asynchronous connection
6566
67+
You can also connect to Redis using an asynchronous API.
68+
The `redisAsyncConnect()` call that creates the context is
69+
similar to the synchronous function `redisConnect()`, but it returns the
70+
context object immediately before the connection is complete.
71+
It lets you supply callbacks to respond when a connection is successful
72+
or to handle any errors that may occur.
73+
74+
The following code creates an asynchronous connection and
75+
sets the context callbacks. Note that you must also include the
76+
`async.h` header to access the asynchronous API.
77+
78+
```c
79+
#include <stdio.h>
80+
81+
#include <hiredis/hiredis.h>
82+
#include <hiredis/async.h>
83+
.
84+
.
85+
.
86+
87+
redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379);
88+
89+
if (c->err) {
90+
printf("Error: %s\n", c->errstr);
91+
return 1;
92+
}
93+
94+
// Set callbacks to respond to successful or unsuccessful
95+
// connection and disconnection.
96+
redisAsyncSetConnectCallback(c, connectCallback);
97+
redisAsyncSetDisconnectCallback(c, disconnectCallback);
98+
99+
char *key = "testkey";
100+
char *value = "testvalue";
101+
102+
// Status reply is ignored.
103+
redisAsyncCommand(c, NULL, NULL, "SET %s %s", key, value);
104+
105+
// Reply handled by `getCallback()` function.
106+
redisAsyncCommand(c, getCallback, key, "GET %s", key);
107+
```
108+
109+
The callback functions have a simple signature that receives
110+
the context object and a status code. See
111+
[Handling errors]({{< relref "/develop/clients/hiredis/handle-replies#handling-errors" >}})
112+
for a list of the possible status codes.
113+
114+
```c
115+
void connectCallback(const redisAsyncContext *c, int status) {
116+
if (status != REDIS_OK) {
117+
printf("Error: %s\n", c->errstr);
118+
return;
119+
}
120+
printf("Connected...\n");
121+
}
122+
123+
void disconnectCallback(const redisAsyncContext *c, int status) {
124+
if (status != REDIS_OK) {
125+
printf("Error: %s\n", c->errstr);
126+
return;
127+
}
128+
printf("Disconnected...\n");
129+
}
130+
```
131+
132+
Use the `redisAsyncCommand()` function to issue Redis commands
133+
with an asynchronous connection. This is similar to the equivalent
134+
synchronous function `redisCommand()` but also lets you supply a callback
135+
and a custom data pointer to process the response to the command. See
136+
[Construct asynchronous commands]({{< relref "/develop/clients/hiredis/issue-commands#construct-asynchronous-commands" >}}) for more
137+
information.
138+
139+
Note that you should normally disconnect asynchronously from a
140+
callback when you have finished using the connection.
141+
Use `redisAsyncDisconnect()` to disconnect gracefully, letting
142+
pending commands execute and activate their callbacks.
143+
Use `redisAsyncFree()` to disconnect immediately. If you do this then
144+
any pending callbacks from commands that have already executed will be
145+
called with a `NULL` reply pointer.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
---
2+
categories:
3+
- docs
4+
- develop
5+
- stack
6+
- oss
7+
- rs
8+
- rc
9+
- oss
10+
- kubernetes
11+
- clients
12+
description: Integrate hiredis with C++ and external frameworks.
13+
linkTitle: Integration guides
14+
title: Integration guides
15+
weight: 50
16+
---
17+
18+
`hiredis` is compatible with C++ and the library source includes a set of
19+
[adapters](https://github.com/redis/hiredis/tree/master/adapters)
20+
to help you use it in conjunction with C and C++ libraries and frameworks.
21+
The pages in this section explain how to integrate `hiredis` into
22+
your app.
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
---
2+
categories:
3+
- docs
4+
- develop
5+
- stack
6+
- oss
7+
- rs
8+
- rc
9+
- oss
10+
- kubernetes
11+
- clients
12+
description: Use `hiredis` in conjunction with the `libevent` framework.
13+
linkTitle: libevent integration
14+
title: Integrate hiredis with a libevent app
15+
weight: 60
16+
---
17+
18+
The [`libevent`](https://libevent.org/) library provides an
19+
implementation of an event loop that lets you call functions
20+
asynchronously in response to events. This guide explains
21+
how to use `hiredis` to connect to a Redis server from a
22+
`libevent` app.
23+
24+
## Install `libevent`
25+
26+
The [`libevent` home page](https://libevent.org/) has links to download
27+
all versions of the library, but you should use the latest version
28+
unless there is a specific version you need to target.
29+
30+
When you have downloaded `libevent`, follow the instructions in the
31+
`README` file to compile and install the library.
32+
33+
## Create a simple app
34+
35+
For a real project, you would build your code with a makefile, but for
36+
this simple test, you can just place it in a file called `main.c` and
37+
build it with the following command (assuming you used `make install` to
38+
install the `libhiredis` and `libevent` libraries):
39+
40+
```bash
41+
cc main.c -L/usr/local/lib -lhiredis -levent
42+
```
43+
44+
See [Build and install]({{< relref "/develop/clients/hiredis#build-and-install" >}})
45+
to learn how to build `hiredis`, if you have not already done so.
46+
47+
Now, add the following code in `main.c`. An explanation follows the
48+
code example:
49+
50+
```c
51+
#include <stdio.h>
52+
#include <stdlib.h>
53+
#include <string.h>
54+
#include <signal.h>
55+
56+
#include <hiredis/hiredis.h>
57+
#include <hiredis/async.h>
58+
#include <hiredis/adapters/libevent.h>
59+
60+
// Callback for the `GET` command.
61+
void getCallback(redisAsyncContext *c, void *r, void *privdata) {
62+
redisReply *reply = r;
63+
char *key = privdata;
64+
65+
if (reply == NULL) {
66+
if (c->errstr) {
67+
printf("errstr: %s\n", c->errstr);
68+
}
69+
return;
70+
}
71+
72+
printf("Key: %s, value: %s\n", key, reply->str);
73+
74+
/* Disconnect after receiving the reply to GET */
75+
redisAsyncDisconnect(c);
76+
}
77+
78+
// Callback to respond to successful or unsuccessful connection.
79+
void connectCallback(const redisAsyncContext *c, int status) {
80+
if (status != REDIS_OK) {
81+
printf("Error: %s\n", c->errstr);
82+
return;
83+
}
84+
printf("Connected...\n");
85+
}
86+
87+
// Callback to respond to intentional or unexpected disconnection.
88+
void disconnectCallback(const redisAsyncContext *c, int status) {
89+
if (status != REDIS_OK) {
90+
printf("Error: %s\n", c->errstr);
91+
return;
92+
}
93+
printf("Disconnected...\n");
94+
}
95+
96+
97+
int main (int argc, char **argv) {
98+
#ifndef _WIN32
99+
signal(SIGPIPE, SIG_IGN);
100+
#endif
101+
102+
// Create the libevent `event_base` object to track all
103+
// events.
104+
struct event_base *base = event_base_new();
105+
106+
redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379);
107+
108+
if (c->err) {
109+
printf("Error: %s\n", c->errstr);
110+
return 1;
111+
}
112+
113+
// Use the Redis libevent adapter to attach the Redis connection
114+
// to the libevent main loop.
115+
redisLibeventAttach(c,base);
116+
117+
redisAsyncSetConnectCallback(c, connectCallback);
118+
redisAsyncSetDisconnectCallback(c, disconnectCallback);
119+
120+
char *key = "testkey";
121+
char *value = "testvalue";
122+
123+
redisAsyncCommand(c, NULL, NULL, "SET %s %s", key, value);
124+
redisAsyncCommand(c, getCallback, key, "GET %s", key);
125+
126+
// Run the event loop.
127+
event_base_dispatch(base);
128+
129+
return 0;
130+
}
131+
```
132+
133+
The code calls
134+
[`event_base_new()`](https://libevent.org/doc/event_8h.html#af34c025430d445427a2a5661082405c3)
135+
to initialize the core
136+
[`event_base`](https://libevent.org/doc/structevent__base.html)
137+
object that manages the event loop. It then creates a standard
138+
[asynchronous connection]({{< relref "/develop/clients/hiredis/connect#asynchronous-connection" >}})
139+
to Redis and uses the `libevent` adapter function `redisLibeventAttach()` to
140+
attach the connection to the event loop.
141+
142+
After setting the [connection callbacks]({{< relref "/develop/clients/hiredis/connect#asynchronous-connection" >}}), the code issues two asynchronous
143+
Redis commands (see
144+
[Construct asynchronous commands]({{< relref "/develop/clients/hiredis/issue-commands#construct-asynchronous-commands" >}})
145+
for more information).
146+
The final step is to call
147+
[`event_base_dispatch()`](https://libevent.org/doc/event_8h.html#a19d60cb72a1af398247f40e92cf07056)
148+
to start the event loop. This will wait for the commands to be processed and
149+
then exit when the Redis connection is closed in the `getCallback()` function.
150+
151+
## Run the code
152+
153+
If you compile and run the code, you will see the following output,
154+
showing that the callbacks executed correctly:
155+
156+
```
157+
Connected...
158+
Key: testkey, value: testvalue
159+
Disconnected...
160+
```
161+
162+
You can use the
163+
[`KEYS`]({{< relref "/commands/keys" >}}) command from
164+
[`redis-cli`]({{< relref "/develop/tools/cli" >}}) or
165+
[Redis Insight]({{< relref "/develop/tools/insight" >}}) to check
166+
that the "testkey" string key was added to the Redis database.

0 commit comments

Comments
 (0)