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
geometry
struct that contains function pointers forarea
andperim
. This acts as our interface.We define
rect
andcircle
structs to represent rectangles and circles.We implement the interface functions for both
rect
andcircle
. These functions take avoid*
parameter, which we cast to the appropriate struct type inside the function.The
measure
function takes avoid*
for the shape and ageometry*
for the interface. It calls the interface functions through the function pointers.In
main
, we create instances ofrect
andcircle
, and correspondinggeometry
structs with the appropriate function pointers.We call
measure
with 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.415927
This 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.