Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 6 additions & 11 deletions content/develop/clients/hiredis/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ Then, in a terminal, go into the `hiredis` folder and run the `make` command to
the dynamically-loaded library for `hiredis` (this has the name `libhiredis.dylib` on
MacOS and `libhiredis.so` on Linux). You can copy this library to your
project folder or run `sudo make install` to install it to `/usr/local/lib`.
You should also copy the header files `hiredis.h`, `alloc.h`, `read.h`, and
`sds.h` to your project.

## Connect and test

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

#include "hiredis.h"
#include <hiredis/hiredis.h>

int main() {
// The `redisContext` type represents the connection
Expand Down Expand Up @@ -81,8 +79,9 @@ int main() {

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

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

See the other pages in this section for more information and examples.
82 changes: 81 additions & 1 deletion content/develop/clients/hiredis/connect.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ and port as its arguments, and returns a context object.
```c
#include <stdio.h>

#include "hiredis.h"
#include <hiredis/hiredis.h>
.
.
.
Expand Down Expand Up @@ -62,4 +62,84 @@ freeReplyObject(reply);
redisFree(c);
```

## Asynchronous connection

You can also connect to Redis using an asynchronous API.
The `redisAsyncConnect()` call that creates the context is
similar to the synchronous function `redisConnect()`, but it returns the
context object immediately before the connection is complete.
It lets you supply callbacks to respond when a connection is successful
or to handle any errors that may occur.

The following code creates an asynchronous connection and
sets the context callbacks. Note that you must also include the
`async.h` header to access the asynchronous API.

```c
#include <stdio.h>

#include <hiredis/hiredis.h>
#include <hiredis/async.h>
.
.
.

redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379);

if (c->err) {
printf("Error: %s\n", c->errstr);
return 1;
}

// Set callbacks to respond to successful or unsuccessful
// connection and disconnection.
redisAsyncSetConnectCallback(c, connectCallback);
redisAsyncSetDisconnectCallback(c, disconnectCallback);

char *key = "testkey";
char *value = "testvalue";

// Status reply is ignored.
redisAsyncCommand(c, NULL, NULL, "SET %s %s", key, value);

// Reply handled by `getCallback()` function.
redisAsyncCommand(c, getCallback, key, "GET %s", key);
```

The callback functions have a simple signature that receives
the context object and a status code. See
[Handling errors]({{< relref "/develop/clients/hiredis/handle-replies#handling-errors" >}})
for a list of the possible status codes.

```c
void connectCallback(const redisAsyncContext *c, int status) {
if (status != REDIS_OK) {
printf("Error: %s\n", c->errstr);
return;
}
printf("Connected...\n");
}

void disconnectCallback(const redisAsyncContext *c, int status) {
if (status != REDIS_OK) {
printf("Error: %s\n", c->errstr);
return;
}
printf("Disconnected...\n");
}
```

Use the `redisAsyncCommand()` function to issue Redis commands
with an asynchronous connection. This is similar to the equivalent
synchronous function `redisCommand()` but also lets you supply a callback
and a custom data pointer to process the response to the command. See
[Construct asynchronous commands]({{< relref "/develop/clients/hiredis/issue-commands#construct-asynchronous-commands" >}}) for more
information.

Note that you should normally disconnect asynchronously from a
callback when you have finished using the connection.
Use `redisAsyncDisconnect()` to disconnect gracefully, letting
pending commands execute and activate their callbacks.
Use `redisAsyncFree()` to disconnect immediately. If you do this then
any pending callbacks from commands that have already executed will be
called with a `NULL` reply pointer.
22 changes: 22 additions & 0 deletions content/develop/clients/hiredis/int-examples/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
categories:
- docs
- develop
- stack
- oss
- rs
- rc
- oss
- kubernetes
- clients
description: Integrate hiredis with C++ and external frameworks.
linkTitle: Integration guides
title: Integration guides
weight: 50
---

`hiredis` is compatible with C++ and the library source includes a set of
[adapters](https://github.com/redis/hiredis/tree/master/adapters)
to help you use it in conjunction with C and C++ libraries and frameworks.
The pages in this section explain how to integrate `hiredis` into
your app.
166 changes: 166 additions & 0 deletions content/develop/clients/hiredis/int-examples/libevent-integration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
---
categories:
- docs
- develop
- stack
- oss
- rs
- rc
- oss
- kubernetes
- clients
description: Use `hiredis` in conjunction with the `libevent` framework.
linkTitle: libevent integration
title: Integrate hiredis with a libevent app
weight: 60
---

The [`libevent`](https://libevent.org/) library provides an
implementation of an event loop that lets you call functions
asynchronously in response to events. This guide explains
how to use `hiredis` to connect to a Redis server from a
`libevent` app.

## Install `libevent`

The [`libevent` home page](https://libevent.org/) has links to download
all versions of the library, but you should use the latest version
unless there is a specific version you need to target.

When you have downloaded `libevent`, follow the instructions in the
`README` file to compile and install the library.

## Create a simple app

For a real project, you would build your code with a makefile, but for
this simple test, you can just place it in a file called `main.c` and
build it with the following command (assuming you used `make install` to
install the `libhiredis` and `libevent` libraries):

```bash
cc main.c -L/usr/local/lib -lhiredis -levent
```

See [Build and install]({{< relref "/develop/clients/hiredis#build-and-install" >}})
to learn how to build `hiredis`, if you have not already done so.

Now, add the following code in `main.c`. An explanation follows the
code example:

```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>

#include <hiredis/hiredis.h>
#include <hiredis/async.h>
#include <hiredis/adapters/libevent.h>

// Callback for the `GET` command.
void getCallback(redisAsyncContext *c, void *r, void *privdata) {
redisReply *reply = r;
char *key = privdata;

if (reply == NULL) {
if (c->errstr) {
printf("errstr: %s\n", c->errstr);
}
return;
}

printf("Key: %s, value: %s\n", key, reply->str);

/* Disconnect after receiving the reply to GET */
redisAsyncDisconnect(c);
}

// Callback to respond to successful or unsuccessful connection.
void connectCallback(const redisAsyncContext *c, int status) {
if (status != REDIS_OK) {
printf("Error: %s\n", c->errstr);
return;
}
printf("Connected...\n");
}

// Callback to respond to intentional or unexpected disconnection.
void disconnectCallback(const redisAsyncContext *c, int status) {
if (status != REDIS_OK) {
printf("Error: %s\n", c->errstr);
return;
}
printf("Disconnected...\n");
}


int main (int argc, char **argv) {
#ifndef _WIN32
signal(SIGPIPE, SIG_IGN);
#endif

// Create the libevent `event_base` object to track all
// events.
struct event_base *base = event_base_new();

redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379);

if (c->err) {
printf("Error: %s\n", c->errstr);
return 1;
}

// Use the Redis libevent adapter to attach the Redis connection
// to the libevent main loop.
redisLibeventAttach(c,base);

redisAsyncSetConnectCallback(c, connectCallback);
redisAsyncSetDisconnectCallback(c, disconnectCallback);

char *key = "testkey";
char *value = "testvalue";

redisAsyncCommand(c, NULL, NULL, "SET %s %s", key, value);
redisAsyncCommand(c, getCallback, key, "GET %s", key);

// Run the event loop.
event_base_dispatch(base);

return 0;
}
```

The code calls
[`event_base_new()`](https://libevent.org/doc/event_8h.html#af34c025430d445427a2a5661082405c3)
to initialize the core
[`event_base`](https://libevent.org/doc/structevent__base.html)
object that manages the event loop. It then creates a standard
[asynchronous connection]({{< relref "/develop/clients/hiredis/connect#asynchronous-connection" >}})
to Redis and uses the `libevent` adapter function `redisLibeventAttach()` to
attach the connection to the event loop.

After setting the [connection callbacks]({{< relref "/develop/clients/hiredis/connect#asynchronous-connection" >}}), the code issues two asynchronous
Redis commands (see
[Construct asynchronous commands]({{< relref "/develop/clients/hiredis/issue-commands#construct-asynchronous-commands" >}})
for more information).
The final step is to call
[`event_base_dispatch()`](https://libevent.org/doc/event_8h.html#a19d60cb72a1af398247f40e92cf07056)
to start the event loop. This will wait for the commands to be processed and
then exit when the Redis connection is closed in the `getCallback()` function.

## Run the code

If you compile and run the code, you will see the following output,
showing that the callbacks executed correctly:

```
Connected...
Key: testkey, value: testvalue
Disconnected...
```

You can use the
[`KEYS`]({{< relref "/commands/keys" >}}) command from
[`redis-cli`]({{< relref "/develop/tools/cli" >}}) or
[Redis Insight]({{< relref "/develop/tools/insight" >}}) to check
that the "testkey" string key was added to the Redis database.
Loading