inteface.h
#define interface(NAME, FNS) \
typedef struct {FNS} NAME ## _implementation; \
typedef struct { void* target; NAME ## _implementation* implementation; } NAME;
#define implements(CLASS, INTERFACE, COUNT, ...) \
typedef union { INTERFACE ## _implementation implementation; void* pointers[COUNT]; } CLASS ## _implementation_of_ ## INTERFACE ## _struct; \
CLASS ## _implementation_of_ ## INTERFACE ## _struct CLASS ## _implementation_of_ ## INTERFACE = { .pointers = {__VA_ARGS__} }; \
INTERFACE CLASS ## To ## INTERFACE(CLASS* this) { INTERFACE result; result.target = this; result.implementation = &CLASS ## _implementation_of_ ## INTERFACE.implementation; return result; }
#define CallInterface(INTERFACE, METHOD, ...) INTERFACE.implementation->METHOD(INTERFACE.target, ## __VA_ARGS__)
istack.h
#include "interface.h"
interface(IStack,
int (*push)(void* this, int value);
int (*pop)(void* this);
int (*peek)(void* this);
int (*size)(void* this);
);
smallstack.c (I removed the implementation for brevity)
#include "istack.h"
#define MAX_STACK_SIZE 20
typedef struct {
int entries[MAX_STACK_SIZE];
int currentIndex;
} SmallStack;
SmallStack* SmallStack_init(SmallStack* this) {
this->currentIndex = 0;
}
int SmallStack_push(SmallStack* this, int value) {...}
int SmallStack_pop(SmallStack* this) {...}
int SmallStack_peek(SmallStack* this) {...}
int SmallStack_size(SmallStack* this) {...}
implements(SmallStack, IStack, 4,
&SmallStack_push,
&SmallStack_pop,
&SmallStack_peek,
&SmallStack_size
);
main.c
int Sum(IStack stack) {
int result = 0;
while (CallInterface(stack, size)) {
result += CallInterface(stack, pop);
}
return result;
}
int main() {
SmallStack smallStack;
SmallStack_init(&smallStack);
SmallStack_push(&smallStack, 10);
SmallStack_push(&smallStack, 5);
SmallStack_push(&smallStack, 2);
printf("Sum: %d\n", Sum(SmallStackToIStack(&smallStack)));
return 0;
}
My question is, would you use something like this? My biggest concern is in the implements macro.You need to specify the methods in the same order and with the same count defined in the interface, otherwise your implementation will be broken. Can you think of a way for the compiler to enforce correct implementation of the interface?