I have to write code in C where the user has to have flexibility in choosing any existing DB, write to files, or implement their own storage mechanism. I need wrapper functions that redirect to the right functions corresponding to the storage mechanism selected at runtime or compile time. Say my storage options are FLATFILE and SQLDB and my wrapper function is insert(value). So, if I select FLATFILE as my storage, when I call the wrapper function insert(value), it should in turn call the function that writes to a file. If I choose a SQLDB, insert(value) should call the fun开发者_JAVA技巧ction that insert the values in the data base.
I know I can somehow use a structure of function pointers to do wrapper functions, but I have no idea how.
Does anyone know of any docs, links, examples, etc I could refer to, to understand and implement something like this? Any pointers will be appreciated. Thanks!
Thanks!
#define BACKEND_FLATFILE 0
#define BACKEND_SQLDB 1
void insert_flatfile(const t_value *v) {
...
}
void insert_sqldb(const t_value *v) {
...
}
void (*insert_functions[]) (const t_value *) = {
insert_flatfile,
insert_sqldb,
};
void insert_wrapper(t_value *v, int backend) {
insert_functions[backend](v);
}
Besides, the different functions for one backend should be stuffed into a struct and you should create an array of such structs instead of one array per wrapper function.
You can use a simple version such as:
struct backend {
int (*insert)(...);
int (*remove)(...);
...
};
static struct backend db_backend = { db_insert, db_remove, ... };
static struct backend other_backend = { other_insert, other_remove, ... };
const struct backend *get_backend(enum backend_type type)
{
switch (type)
{
case DB_BACKEND:
return &db_backend;
case DB_OTHER:
return &db_other;
...
}
}
All of the above can be hidden inside a C file, with get_backend
and the enumeration being public. Then you can use it like this:
struct backend *b = get_backend(DB_BACKEND);
b->insert(...);
b->remove(...);
Many details are missing, of course (many people like using typedef
, for example). This is a basic setup, you can also create wrapper functions if you don't like the b->insert(...)
syntax or if you want to set the back end once and then use insert()
and remove()
in the code. This is also useful if you already have some code that calls insert()
directly and you want to direct the call to the right back end.
If you want a more elaborate solution, have a look at http://www.cs.rit.edu/~ats/books/ooc.pdf. You don't have to implement every last detail from it, but it can give you a few ideas.
精彩评论