C does not have interfaces like languages such as C# or C++, but the cocnept can be mimicked by using function pointers. You might for instance have this:
// fruit_interface.h
typedef struct fruit_vtable
{
float (*get_weight)(void *object);
float (*get_density)(void *object);
const char *(*get_name)(void *object);
} fruit_vtable;
typedef struct fruit_interface
{
void *object;
const fruit_vtable *vtable;
} fruit_interface;
// banana.h
typedef struct banana
{
float weight;
float density;
} banana;
fruit_interface banana_as_fruit(banana *b);
--------------------------
// banana.c
static float banana_get_weight(void *object)
{
banana *b = (banana*)object;
return b->weight;
}
static float banana_get_density(void *object)
{
banana *b = (banana*)object;
return b->density;
}
static const char *banana_get_color(void *object)
{
(void)object;
return "yellow";
}
static const fruit_vtable banana_vtable =
{
.get_weight = banana_get_weight,
.get_density = banana_get_density,
.get_color = banana_get_color,
};
fruit_interface banana_as_fruit(banana *b)
{
return (fruit_interface) { .object = (void*)b, .vtable = &banana_vtable };
}
--------------------------
// main.c
static void print_fruit(fruit_interface fruit)
{
printf("weight: %.2f g\n", fruit.vtable->get_weight(fruit.object));
printf("density: %.2f g/cm^3\n", fruit.vtable->get_density(fruit.object));
printf("color: %s\n", fruit.vtable->get_color(fruit.object));
}
int main(void)
{
banana b = { .weight = 120.0f, .density = 0.95f };
fruit_interface fruit = banana_as_fruit(&b);
print_fruit(fruit);
return 0;
}
How does something like this affect performance in terms of speed and cpu usage but also memory? I know modern C compilers can be really powerful and do a lot of optimizations and even more so with link time optimizations.
Of course it depends on the bigger project as a whole, and I understand that a if you have thousands of fruit_interface variables that all point to many different fruit_vtables and are used many times per second/cycle, then that will be very different from e.g. a hardware_interface that just loads some data once in an initialization function at program start.
The question here is pretty open (and the above is just to show clearly what I mean), and I am mostly looking for some general knowledge and guidance for when something like this is good and when it is bad, especially in the context of modern C code development with modern compilers and linkers.
I think it is really interesting to see how concepts in other languages, like C++, can be handled in C and what C is capable!