3

I work with embedded software and have encountered (as well as copied from this model) an interface I never learned about in college (new grad). It allows a code base to make a library function call without knowing what library is compiled with it, assuming they both have the same function. The example below only shows a radio1, but assume there is a radio2, radio3, etc that is handled via the makefile.

In a compiled library we do the following. In a .c source file, the function declarations and the interface struct:

// function bodies that do things
void radio1_init_radio(void) {}
void radio1_calibrate_radio(void) {} 

// populate global tune interface
const struct tune_if_t tune_if =
{
    .init_radio        = radio1_init_radio,
    .calibrate_radio   = radio1_calibrate_radio
}

Then, in a .h I specify the function pointers:

struct tune_if_t
{
    void (*init_radio)      (void);
    void (*calibrate_radio) (void);
};

extern const struct tune_if_t tune_if;

This allows the system outside of the library to call a function without knowing which radio library is compiled and linked with it:

int main( void )
{
    // interface calls
    tune_if.init_radio();
    tune_if.calibrate_radio();

    return 0;
}

My questions are:

  • Is there a technical term for this? It's kind of hard for me to explain to another engineer quickly at the moment.

  • Is this the best approach to accomplishing this type of behavior?

  • Are there any issues with this approach?

Allen
  • 162
  • 2
  • 3
  • 15
  • 3
    I would call it a compile time "plugin". Not sure if that is the best name for it. – kaylum Jun 02 '16 at 06:34
  • The method is called *object-oriented programming*. The struct that holds function pointers is sometimes called *vtable* (from "virtual table"). Normally each such function should get a "context" parameter that points to *instance data*, but in your case they seemingly use some kind of static instance data. – n. m. could be an AI Jun 02 '16 at 06:36

4 Answers4

5

I don't know if it has a more specific name in C, but it's a form of polymorphism. It's related to inheritance and virtual functions in C++.

Community
  • 1
  • 1
Owen
  • 38,836
  • 14
  • 95
  • 125
2

Note: To long for a comment, but not really an answer to the question.

When you say "library", do you mean e.g. a static or dynamic library that you link to at built-time? Or just a source file whose object file you link to at build-time? Either way I recommend you don't use a global variable for the structure, instead I suggest you have a specially named function which takes a pointer to the tune_if_t structure as argument and fills it in. If all users of the "library" will use the same functions then have the structure be a static structure inside the function, and just copy it.

This way it's easier to have the function take some extra argument and the "library" can at run-time decide which functions it should use. This way will also make it easier to make the library a dynamic loadable module, where different processes can, at run-time, load your library.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • By "library" I mean a static library that is linked at build-time. But the library is also a series of custom-built source/header files, so perhaps "library" is being used loosely here.. Basically the structure is a common "base" that is supported by one of many libraries. At compile time my makefile calls the makefile of the library I specify, and then that library is then linked at compile time with the "common base" I mentioned before. Thanks for the recommendation by the way! – Allen Jun 02 '16 at 06:33
1

To me this looks very similar to plug-ins. The difference is that with plug-ins application selects library at run-time, while here you link it statically, so you need to select implementation at compile time.

dbrank0
  • 9,026
  • 2
  • 37
  • 55
0

It is nothing but function pointers (init_radio and calibrate_radio).[Also called call-back mechanism]

You must be confused with .operator inside the structure. It is a GNU style and tells the compiler to assign address of function radio1_init_radio to function pointer init_radio & address of function radio1_calibrate_radio to calibrate_radio function pointer

And yes, it is how polymorphism is implemented in C

Harsha
  • 323
  • 1
  • 17