Okay, I browsed through the source code of the giflib, and realized that the callback should replace fread.
typedef int (*InputFunc) (GifFileType *, GifByteType *, int);
The first argument is the gif handle, the second is the destination buffer, and the third is the length of data, that should be read. Return value is, equivalent to fread, the number of bytes that were read. Additional data can be passed in the userPointer when the callback is registered:
DGifOpen ( void *userPointer, InputFunc *func)
The userPointer can be accessed as a member of the gif handle (pGifHandle->userData)
The same way, you can use a write callback.
Register your function and a pointer to custom data in
EGifOpen ( void *userPointer, OutputFunc *func)
where OutputFunc takes the gif handle as the first argument, the buffer as the second, and the number of bytes to write as third. The return value is the number of bytes written.