chriso / example.c secret
Created

Embed URL

HTTPS clone URL

SSH clone URL

You can clone with HTTPS or SSH.

Download Gist

Prototypal inheritance in C

View example.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
/* (c) Chris O'Hara 2011 - MIT License */
 
#include <stdio.h>
#include <stdlib.h>
#include "prototype.h"
 
#ifndef NDEBUG
#define debug(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else
#define debug(fmt, ...)
#endif
 
void constructor(void *, char *);
void destructor(void *);
void greet(void *);
void trollGreet(void *);
 
INTERFACE(
char *name;
void (*construct)(void *self, char *name);
void (*destruct)(void *self);
void (*greet)(void *self);
);
 
PROTOTYPE(Person,
/* no member vars */
, .construct = constructor
, .destruct = destructor
, .greet = greet
);
 
PROTOTYPE_INHERIT(Troll, Person,
int trollFactor;
, .greet = trollGreet
);
 
int main(int argc, char **argv) {
Person *chris = CONSTRUCT(Person, "Chris");
Troll *troll = CONSTRUCT(Troll, "Bob");
 
troll->trollFactor = 20;
 
CALL(chris, greet);
CALL(troll, greet);
 
DESTRUCT(chris);
DESTRUCT(troll);
 
return 0;
}
 
void constructor(void *self, char *new) {
debug("(Constructing %s)\n", new);
SET(self, name, new);
}
 
void destructor(void *self) {
debug("(Destructing %s)\n", GET(self, name));
}
 
void greet(void *self) {
debug("(Greeting %s)\n", GET(self, name));
printf("%s: hello\n", GET(self, name));
}
 
void trollGreet(void *self) {
SUPER(self, greet);
 
int trollFactor = ((Troll *)self)->trollFactor;
 
printf("%s: also, F", GET(self, name));
while (trollFactor--) putchar('U');
putchar('\n');
}
View example.c
1 2 3 4 5 6 7 8 9
(Constructing Chris)
(Constructing Bob)
(Greeting Chris)
Chris: hello
(Greeting Bob)
Bob: hello
Bob: also, FUUUUUUUUUUUUUUUUUUUU
(Destructing Chris)
(Destructing Bob)
View example.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
/* (c) Chris O'Hara 2011 - MIT License */
/* Language hack alert - don't use this for anything ever. */
 
#ifndef __PROTOTYPE_H
#define __PROTOTYPE_H
 
#if !defined(__GNUC__) || __STDC_VERSION__ != 199901L
# error GNU99 is required
#endif
 
#ifndef PROTOTYPE_CALLOC
#define PROTOTYPE_CALLOC calloc
#endif
 
#ifndef PROTOTYPE_FREE
#define PROTOTYPE_FREE free
#endif
 
#define INTERFACE(methods) \
typedef struct proto_s Prototype; \
struct proto_s { Prototype *proto; methods }
 
#define PROTOTYPE(prototype, members, ...) \
typedef struct prototype##_s prototype; \
struct prototype##_s { Prototype proto; members }; \
Prototype prototype##Proto = { .proto = NULL, ##__VA_ARGS__ }
 
#define PROTOTYPE_INHERIT(prototype, parent, members, ...) \
typedef struct prototype##_s prototype; \
struct prototype##_s { Prototype proto; members }; \
Prototype prototype##Proto = { .proto = &parent##Proto, ##__VA_ARGS__ }
 
#define NEW(Obj) \
({ Prototype *proto = PROTOTYPE_CALLOC(sizeof(Obj), 1); \
*proto = Obj##Proto; \
(Obj *) proto; })
 
#define DESTROY(Obj) \
(PROTOTYPE_FREE((void *)Obj))
 
#define CONSTRUCT(Obj, ...) \
({ Prototype *obj = (void *)NEW(Obj), *proto = obj; \
while (proto != NULL && proto->construct == NULL) \
proto = proto->proto; \
if (proto->construct) \
proto->construct(proto, ##__VA_ARGS__); \
(Obj *) obj; })
 
#define DESTRUCT(Obj, ...) \
do { Prototype *obj = (void *)Obj, *proto = obj; \
while (proto != NULL && proto->destruct == NULL) \
proto = proto->proto; \
if (proto && proto->destruct) \
proto->destruct(proto, ##__VA_ARGS__); \
DESTROY(obj); } while (0)
 
#define CALL(Obj, method, ...) \
(((Prototype *)(void *)Obj)->method \
? ((Prototype *)(void *)Obj)->method(Obj, ##__VA_ARGS__) \
: ({ Prototype *proto = (void *)Obj, *top = proto; \
while (proto != NULL && proto->method == NULL) \
proto = proto->proto; \
proto && (top->method = proto->method) \
? proto->method(Obj, ##__VA_ARGS__) : 0; }))
 
#define SUPER(Obj, method, ...) \
CALL(((Prototype *)(void *)Obj)->proto, method, ##__VA_ARGS__)
 
#define GET(Obj, member) \
(((Prototype *)(void *)Obj)->member \
? ((Prototype *)(void *)Obj)->member \
: ({ Prototype *proto = (void *)Obj, *top = proto; \
while (proto != NULL && proto->member == NULL) \
proto = proto->proto; \
proto && (top->member = proto->member) \
? proto->member : 0; }))
 
#define SET(Obj, member, value) \
(((Prototype *)(void *)Obj)->member = value)
 
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.