# FFI wrapper for a callback with variable number of arguments

**URL:** https://racket.discourse.group/t/ffi-wrapper-for-a-callback-with-variable-number-of-arguments/1416
**Category:** Questions & Answers
**Tags:** ffi
**Created:** [October 28, 2022, 6:23pm UTC](https://racket.discourse.group/t/ffi-wrapper-for-a-callback-with-variable-number-of-arguments/1416 "2022-10-28T18:23:32Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![wluker](https://avatars.discourse-cdn.com/v4/letter/w/0ea827/32.png) [@wluker](https://racket.discourse.group/u/wluker)
#### Post date: [October 28, 2022, 6:23pm UTC](https://racket.discourse.group/t/ffi-wrapper-for-a-callback-with-variable-number-of-arguments/1416/1 "2022-10-28T18:23:32Z")

</div>

In the GEOS C library a variadic `printf` like function is required as a callback for error reporting and I am unsure how to wrap that with racket's FFI.

There is a racket ffi [example](https://github.com/racket/racket/blob/master/pkgs/racket-doc/ffi/examples/c-printf.rkt) of how to wrap `printf` where the types and number of arguments are determined and then `_cprocedure` is called with those types. It makes sense, but I'm not sure how to define the callback when the argument types and number are not known beforehand.

The `_cprocedure` [docs](https://docs.racket-lang.org/foreign/foreign_procedures.html#%28def._%28%28lib._ffi%2Funsafe..rkt%29.__cprocedure%29%29) say something about a `#:varargs-after 1` parameter could be used, but then it goes on to say that you need a different `_cprocedure` for each combination of argument type and number; which I'm not sure how to define for a callback.

**The corresponding C code is ::**

The C function pointer type is :

```
typedef void (*GEOSMessageHandler)(const char *fmt, ...);

```

An example callback in C could be :

```
static void geos_msg_handler(const char* fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    vprintf (fmt, ap);
    va_end(ap);
}

```

And the C callback is registered with this :

```
void initGEOS( GEOSMessageHandler notice_function, GEOSMessageHandler error_function);

```

Does anyone have some insights on how to approach this?

---

<div class="post-metadata">

### Author: ![mflatt](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/mflatt/32/6_2.png) [@mflatt](https://racket.discourse.group/u/mflatt)
#### Post date: [October 29, 2022, 10:57pm UTC](https://racket.discourse.group/t/ffi-wrapper-for-a-callback-with-variable-number-of-arguments/1416/2 "2022-10-29T22:57:06Z")

</div>

There's not currently a way to do this at the Racket level. The FFI would have to provide something like a `va_list` interface, which is not straightforward to implement.

If you only need an approximation to the output, then you could just not use any arguments after the first one — but do use `#:varargs-after 1` with a callback that expects one argument.

Otherwise, I can't think of a way to do this other than create a helper C library with a function that uses `vsprintf` and then sends the string on to another callback (that could be in Racket).

---

<div class="post-metadata">

### Author: ![wluker](https://avatars.discourse-cdn.com/v4/letter/w/0ea827/32.png) [@wluker](https://racket.discourse.group/u/wluker)
#### Post date: [October 31, 2022, 2:11pm UTC](https://racket.discourse.group/t/ffi-wrapper-for-a-callback-with-variable-number-of-arguments/1416/3 "2022-10-31T14:11:08Z")

</div>

> There's not currently a way to do this at the Racket level. The FFI would have to provide something like a `va_list` interface, which is not straightforward to implement.

I can appreciate that. It does seem like variadic functions in C are a wart. To be honest, even if `va_list` were available in racket I'm not sure I would want to parse the format string to figure out the types anyway.

> Otherwise, I can't think of a way to do this other than create a helper C library with a function that uses `vsprintf` and then sends the string on to another callback (that could be in Racket).

This seems reasonable with a callback that uses a custom `log-error`. Thanks!
