There is more than one way to trick this particular cat, but in general, the solution to this problem hides the implementation of the public interface behind indirectness, which allows you to introduce separate "implementations".
(This embodiment of your problem is also closely related to a slightly different problem of ensuring ABI compatibility between code versions.)
To solve this problem in C, you can do it similarly to pimpl with-inheritance in C ++ (protected instead of a private d-pointer with overridden protected constructors):
You create an opaque object 'reader' / 'stream' (a pointer to redirecting the declared w / typedef structure to C) and the corresponding constructor functions to create an instance of an opaque object that introduces the desired implementation.
Let me sketch out sample header files to give you an idea of how functions fit together. Let's start with the guts, the definition of d-pointer / p-impl objects (NB: I omit some patterns, such as guards):
reader-private.h :
struct FileReaderPrivateData { FILE * fp; }; struct StringReaderPrivateData { size_t nlines; size_t cursor; char ** lines; }; struct ReaderPrivate { int (* close)(void* pData); ssize_t (* readLine)(void* pData, char** into); void * data; }; struct Reader { struct ReaderPrivate * dPtr; }
reader.h
typedef struct Reader* Reader; ssize_t readLine(Reader r, char ** buf); int close(Reader r);
file-reader.h
#include "reader.h" Reader createFileReader(FILE * fp); Reader createFileReader(const char* path);
string-reader.h
#include "reader.h" Reader createStringReader(const char**, size_t nlines);
This is a common template for executing a pimpl / d pointer with C inheritance, so you can ignore the implementation context behind the open interface that is accessed through opaque pointers. This mechanism is usually useful for ensuring API and ABI compatibility between different implementations of an open interface and for implementing a simple inheritance pattern.
source share