3

I am new to hiredis and use v0.13. I noticed that the API functions from hiredis.h, which deal with redisReply* objects, all use void*. For example,

void *redisCommand(redisContext *c, const char *format, ...);

returns a redisReply* object (or NULL);

int redisGetReply(redisContext *c, void **reply);

outputs a redisReply* object through reply;

void freeReplyObject(void *reply);

is, according to the code comment, a “Function to free the reply objects hiredis returns by default.”

What am I missing here—why do these functions use void* instead of redisReply*?

edavid
  • 371
  • 1
  • 3
  • 5

2 Answers2

3

I noticed that the API functions from hiredis.h, which deal with redisReply* objects, all use void*

The only sensible way I can see to interpret your description is that you've analyzed the implementation to find that internally, it uses pointers to a type named redisReply, but the interface deals with such pointers via type void * instead.

That would be a mechanism for forcing clients of that API to handle the reply object pointers as opaque values. Clients (presumably) don't have have the definition of redisReply, or even its name, and there is no declared association between the reply pointers and that type, so the API explicitly avoids providing a way for clients to create such objects or interpret or modify their values other than via the API's own functions. All they can do is receive those opaque pointers from the API and pass them back.

I will also say, however, that this particular approach to opaque pointers is a poor one. It is possible to provide much better type safety without giving up opacity, as demonstrated in the answer to the question linked above.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
1

Generic functions are written often this way as you can cast any pointer to void * and void * to the same pointer (same about the char pointer types) without the risk and portable. You also will not get any compiler warnings.

0___________
  • 60,014
  • 4
  • 34
  • 74
  • 2
    The functions in OP’s example are (ostensibly) *not* generic. That said, I haven’t looked at the implementation … it’s conceivable that this is an opaque pointer and the actual, internal object type is something different that happens to be layout compatible with `redisReply*`. But even in that case using `void*` instead of `redisReply*` in the public interface doesn’t really make sense. – Konrad Rudolph Jun 21 '19 at 13:42
  • I’m assuming that OP’s information is correct and complete, and corresponds to the API documentation. They said that “[that function] returns a `redisReply*`” so that’s my working hypothesis. Admittedly it seems unlikely that these assumptions are all correct, if we also assume that the developers of that API know what they’re doing. – Konrad Rudolph Jun 21 '19 at 16:17
  • No this function is not returning this type only the `void *` . What is in the return statement does not matter – 0___________ Jun 21 '19 at 16:56
  • To be honest, the hiredis documentation is not very precise—I was hoping that someone with experience using it could give some advice. Anyway, here is a concrete statement from hiredis.h: https://github.com/redis/hiredis/blob/master/hiredis.h#L100-L101 `/* This is the reply object returned by redisCommand() */ typedef struct redisReply { ... ` Further down is the function declaration https://github.com/redis/hiredis/blob/master/hiredis.h#L285 ` void *redisCommand(redisContext *c, const char *format, ...); ` – edavid Jun 24 '19 at 08:51