On GNU systems, if you want to generalize printf, all you need is vfprintf - because there is:
"fmemopen(3)" that creates FILE* that writes to pre-allocate dbuffer
"open_memstream(3)" that creates FILE* that writes to auto-allocated buffer;
and if that's not sufficient, there is "fopencookie(3)" which takes general callbacks and creates FILE* that redirects all operations to those callbacks.
If that does not work for some reason, then having custom callback with user-passed 3 parameters is too much. Why add dedicated FILE* or "size" parameters which are only ever used in one specific case? Do a generic "void * context" argument ("int (write)(char data, void * context)" + "void * context") and let user figure out how to use it.
On GNU systems, if you want to generalize printf, all you need is vfprintf - because there is:
"fmemopen(3)" that creates FILE* that writes to pre-allocate dbuffer
"open_memstream(3)" that creates FILE* that writes to auto-allocated buffer;
and if that's not sufficient, there is "fopencookie(3)" which takes general callbacks and creates FILE* that redirects all operations to those callbacks.
If that does not work for some reason, then having custom callback with user-passed 3 parameters is too much. Why add dedicated FILE* or "size" parameters which are only ever used in one specific case? Do a generic "void * context" argument ("int (write)(char data, void * context)" + "void * context") and let user figure out how to use it.