Skip to content

Instantly share code, notes, and snippets.

@FedeDP
Last active December 18, 2020 07:53
Show Gist options
  • Save FedeDP/ef0150580ff15dd22ffa5a7d58a0150d to your computer and use it in GitHub Desktop.
Save FedeDP/ef0150580ff15dd22ffa5a7d58a0150d to your computer and use it in GitHub Desktop.
Stupidly simple set of macros to mimic GO-like INTERFACE in C
#include <stdio.h>
#include <stddef.h>
#include <string.h>
/*
* PROs:
* * can have variables too as interface members
*
* CONs:
* * INTERFACE type can be directly declared and used as a normal struct
* * INTERFACE_EMBED() macros injects a field in the struct
*/
#define INTERFACE(interface, ...) typedef struct { __VA_ARGS__ } interface
#define INTERFACE_EMBED(interface) interface _interface
#define INTERFACE_OF(ptr, interface) ((interface *)ptr + offsetof(typeof(*ptr), _interface))
#define INTERFACE_INIT(ptr, interface, ...) memcpy(INTERFACE_OF(ptr, interface), &(interface){ __VA_ARGS__ }, sizeof(interface));
static void foo(void);
// Declare the interface, in this case named "test" with 2 fields, an int and a function pointer
INTERFACE(test,
int val;
void (*cb)(void);
);
// Declare a struct that implements "test" interface.
// Note, test interface member must still be initialized.
typedef struct {
int bar;
double x;
INTERFACE_EMBED(test);
} myS;
static void foo(void) {
printf("World\n");
}
static void my_test(test *t) {
printf("Hello %d!\n", t->val);
t->cb();
}
int main() {
myS t = {0};
// Init interface members
INTERFACE_INIT((&t), test, 5, foo);
// Call a function on interface
my_test(INTERFACE_OF((&t), test));
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment