tyler569 icon

C "classes" with vtable

tyler569 | PRO | 09/01/18 06:24:10 PM UTC | 0 ⭐ | 796 👁️ | Never ⏰ | []
C |

2.86 KB

|

None

|

0 👍

/

0 👎

 
#include <stdio.h>
#include <stdlib.h>
 
struct class_typeinfo {
    char *name;
};
typedef struct class_typeinfo class_typeinfo;
 
#define METHODS(methods...) methods
#define MEMBERS(members...) members
 
#define CLASS_VTBL(name) _##name##_vtable_
#define CLASS_MTHD(name, method) _##name##_##method##_
 
#define CLASS_DECL(name, methods, members)  \
typedef struct name name;                   \
struct CLASS_VTBL(name) {                   \
    void (*init)(name *);                   \
    void (*destroy)(name *);                \
    class_typeinfo typeinfo;                \
    methods                                 \
};                                          \
struct CLASS_VTBL(name) CLASS_VTBL(name);   \
struct name {                               \
    struct CLASS_VTBL(name) vtable;         \
    members                                 \
};
 
#define ARGS(args...) args
#define IMPLEMENT(class, method, return_t, args, body...) \
return_t CLASS_MTHD(class, method)(args) {  \
    body                                    \
}
 
#define CTOR(class, body...)                \
void _##class##_init##_(class *self) {      \
    body                                    \
}
#define DTOR(class, body...)                \
void _##class##_destroy##_(class *self) {   \
    body                                    \
}
 
#define NEW(class)                          \
class *tmpname = malloc(sizeof(class));     \
tmpname->vtable = CLASS_VTBL(class);        \
tmpname->vtable.init(tmpname);
 
#define METHODCALL(object, method, args...) \
    object->vtable.method(object, ## args)
 
 
CLASS_DECL(foo,
METHODS(
    int (*inc)(foo *self);
    int (*dec)(foo *self);
    void (*set)(foo *self, int new_value);
    int (*get)(foo *self);
),
MEMBERS(
    int local;
)
);
 
CTOR(foo,
    self->local = 0;
);
 
DTOR(foo, {});
 
IMPLEMENT(foo, inc, int, ARGS(foo *self),
    self->local += 1;
    return self->local;
);
IMPLEMENT(foo, dec, int, ARGS(foo *self),
    self->local -= 1;
    return self->local;
);
IMPLEMENT(foo, set, void, ARGS(foo *self, int new_value),
    self->local = new_value;
);
IMPLEMENT(foo, get, int, ARGS(foo *self),
    return self->local;
);
 
int main() {
 
    // until I figure out how to actually put these in the struct AOT.
    CLASS_VTBL(foo).init = _foo_init_;
    CLASS_VTBL(foo).destroy = _foo_destroy_;
    CLASS_VTBL(foo).inc = _foo_inc_;
    CLASS_VTBL(foo).dec = _foo_dec_;
    CLASS_VTBL(foo).set = _foo_set_;
    CLASS_VTBL(foo).get = _foo_get_;
 
    NEW(foo);
    foo *obj = tmpname;
 
    printf("obj->local starts at %i\n", obj->local);
 
    METHODCALL(obj, inc);
    METHODCALL(obj, inc);
    METHODCALL(obj, dec);
 
    printf("obj->inc() returns %i\n", METHODCALL(obj, inc));
 
    METHODCALL(obj, set, 10);
 
    printf("obj->get() after setting to 10 is %i\n", METHODCALL(obj, get));
}

Comments