I've written a couple of libraries since beginning to use C again last year. One thing that still needs addressing in both of these is the correct use of array-based lists - hereafter, ArrayLists.
At present I tend to do one-off array allocations (usually static allocation) based on library constants (
defines) that may be tweaked by the user before compile. Usually I use arrays of pointers or small values, so memory lost by allocating excessive sizes is of little concern.
This approach is fine for many cases but not for all. For example, right now I need to implement the Observer pattern as part of one these libraries, and it seems wise to have a dynamically-sized array for the subscriber lists stored on the publisher. So it seems the right time to set up ArrayLists for all cases, replacing my old fixed-size arrays for the most part.
My question is about the details of this as it pertains to general-use libraries. There are many ArrayList implementations out there and it would be naive of me to assume that mine is any better than those others. I do not want to force my implementation on anyone; or, put another way, just because you choose to use my library does not mean I want you to use my naive ArrayList. Not only that, but in many cases, if my library is used in a given project, it would seem natural to be using your own ArrayList implementation across all code in that project, rather than mine for certain stuff, and yours for other stuff - it should be uniform.
Here's how I think I should tackle this in C, using publisher/subscriber as the example:
- In the header, declare interface functions to wrap different implementations, so e.g.
publisher_add_subscriber()would wrap an
add()call for some ArrayList, could be yours, mine, or someone else's: point being that different implementations could be swapped in/out;
- ensure that any functions thus implemented using my default ArrayList implementation are not part of the library's main source file, but rather are kept in a separate source file so that it is trivial to reimplement them.
Are there any obvious problems with this assumed course? Suggestions or alternatives?
P.S. FWIW, my C is very object-oriented in nature; perhaps this will better inform your responses.
P.P.S. One obvious answer might appear to be, "Your ArrayList is an implementation detail and so should anyway be hidden behind a suitably opaque interface, thus making it irrelevant." There is some truth to this, except for two things: (1) C exposes all data, and for this reason I like having access to similar data structures across the board when choosing to access internals; (2) one could choose to swap in another ArrayList implementation for performance reasons.