Interfaces in C
#include <stdio.h>
#include <math.h>
// Here's a basic interface for geometric shapes.
typedef struct {
double (*area)(void*);
double (*perim)(void*);
} geometry;
// For our example we'll implement this interface on
// `rect` and `circle` types.
typedef struct {
double width, height;
} rect;
typedef struct {
double radius;
} circle;
// To implement an interface in C, we need to define functions
// that match the function pointers in the interface.
// Here we implement `geometry` on `rect`s.
double rect_area(void* r) {
rect* rect_ptr = (rect*)r;
return rect_ptr->width * rect_ptr->height;
}
double rect_perim(void* r) {
rect* rect_ptr = (rect*)r;
return 2 * rect_ptr->width + 2 * rect_ptr->height;
}
// The implementation for `circle`s.
double circle_area(void* c) {
circle* circle_ptr = (circle*)c;
return M_PI * circle_ptr->radius * circle_ptr->radius;
}
double circle_perim(void* c) {
circle* circle_ptr = (circle*)c;
return 2 * M_PI * circle_ptr->radius;
}
// If a variable has an interface type, then we can call
// methods that are in the named interface. Here's a
// generic `measure` function taking advantage of this
// to work on any `geometry`.
void measure(void* g, geometry* geom) {
printf("Area: %f\n", geom->area(g));
printf("Perimeter: %f\n", geom->perim(g));
}
int main() {
rect r = {width: 3, height: 4};
circle c = {radius: 5};
// The `circle` and `rect` struct types both
// implement the `geometry` interface so we can use
// instances of these structs as arguments to `measure`.
geometry rect_geometry = {rect_area, rect_perim};
geometry circle_geometry = {circle_area, circle_perim};
printf("Rectangle:\n");
measure(&r, &rect_geometry);
printf("\nCircle:\n");
measure(&c, &circle_geometry);
return 0;
}This C code demonstrates the concept of interfaces using function pointers. Here’s a breakdown of the changes and explanations:
We define a
geometrystruct that contains function pointers forareaandperim. This acts as our interface.We define
rectandcirclestructs to represent rectangles and circles.We implement the interface functions for both
rectandcircle. These functions take avoid*parameter, which we cast to the appropriate struct type inside the function.The
measurefunction takes avoid*for the shape and ageometry*for the interface. It calls the interface functions through the function pointers.In
main, we create instances ofrectandcircle, and correspondinggeometrystructs with the appropriate function pointers.We call
measurewith each shape and its corresponding geometry interface.
To compile and run this program:
$ gcc -o interfaces interfaces.c -lm
$ ./interfaces
Rectangle:
Area: 12.000000
Perimeter: 14.000000
Circle:
Area: 78.539816
Perimeter: 31.415927This example demonstrates how to simulate interfaces in C using function pointers. While C doesn’t have built-in support for interfaces like some higher-level languages, this pattern allows for a similar level of abstraction and polymorphism.