Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free.

I am starting a side project in C which requires multiple storage backends to be driven by a particular piece of logic. These storage backends would each be linked with the decision of which one to use specified at runtime.

So for example if I invoke my program with one set of parameters it will perform the operations in memory but if I change the program configuration it would write to disk.

The underlying idea is that each storage backend should implement the same protocol. In other words the logic for performing operations should need to know which backend it is operating on.

Currently the way I have thought to provide this indirection is to have a struct of function pointers with the logic calling these function pointers. Essentially the struct would contain all the operations needed to implement the higher level logic E.g.

struct Context {
    void (* doPartOfDoOp)(void)
    int (* getResult)(void); 
}

//logic.h
void doOp(Context * context) {
    //bunch of stuff
    context->doPartOfDoOp();
}

int getResult(Context * context) {
    //bunch of stuff
    return context->getResult();
} 

My questions is if this way of solving the problem is one a C programmer would understand? I am a Java developer by trade but enjoy using C/++. Essentially the Context struct provides an interface like level of indirection. However I would like to know if there is a more idiomatic way of achieving this.

share|improve this question
    
Looks like you are doing OOP in C. I've certainly seen stuff like that. –  Steven Burnap Oct 18 '13 at 23:08
1  
Yes, storing function pointers in a struct and mapping behavior based upon these pointers is quite typical (see ioctls). –  ChuckCottrill Oct 19 '13 at 3:16

1 Answer 1

up vote 3 down vote accepted

Yes, a seasoned C programmer would certainly understand such constructs. Using function pointers is just about the only way you have in C to select at runtime which of a set of functions to execute.

Ans storing function pointers in a struct gives a very clear signal that those functions belong together and is a very common way to emulate methods/member-functions in C.


One change I would advise is to pass the Context struct also as a 'this pointer' to the function pointers, like this:

struct Context {
    void (* doPartOfDoOp)(struct Context*)
    int (* getResult)(struct Context*); 
};

//logic.h
void doOp(Context * context) {
    //bunch of stuff
    context->doPartOfDoOp(context);
}

int getResult(Context * context) {
    //bunch of stuff
    return context->getResult(context);
}

In C, if you have a pointer to the first member of a struct, then you can cast that pointer to the struct type itself and use it to access the other members. This allows you to build a kind of inheritance tree and makes it possible to give your back-ends "member variables", like this:

struct FileBackend {
    struct Context interface;
    FILE* file;
}

void doPartOfDoOpFileBackend(struct Context* context)
{
    struct FileBackend* this = (struct FileBackend)context;
    // do stuff, accessing the file through this->file.
}
share|improve this answer
    
Makes a lot of sense. Thanks for the answer. –  ahjmorton Oct 22 '13 at 19:10

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.