FFI wrapper for a callback with variable number of arguments

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 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 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?

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).

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!