Quikest way to implement C++ style OOP in C99
Sometimes it is useful to pack functions and related data into some single struct.
Yet without language support it can be a bit tedious.
Here is a set of macros to do that easier than in C++.
To implement a template class, just put your class code inside the header, and then
#define CLASS
just before including it.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define NOOP_IMPLEMENTATION
#include "noop.h"
#define CLASS CObj
METHODS
void (*foo)(int a);
int (*bar)(int a);
CObj *(*set_xy)(int nx, int ny);
BDATA
int x;
int y;
EDATA
METH(void,foo,int a)
printf("foo a=%d x=%d y=%d\n", a, this.x, this.y);
printf("self.bar returned %d\n", self.bar(a+3));
METH(int,bar,int a)
printf("bar a=%d x=%d y=%d\n", a, this.x, this.y);
return a * 2;
METH(CObj*,set_xy,int nx, int ny)
this.x = nx;
this.y = ny;
return &this;
CTOR
o->x = 123;
o->y = 456;
END
int main(int argc, char **argv) {
CObj *a = new(CObj);
CObj *b = new(CObj);
$(a).set_xy(111,333);
printf("a...\n");
$(b).foo(69);
printf("b...\n");
$(a).foo(7);
return 0;
}
#ifndef NOOP_H
#define NOOP_H
extern void *gthis_;
#define new(type) type##_init(malloc(sizeof(type)))
#define $(o) ((gthis_=(o)), *((o)->vtbl_))
#define self $(this_)
#define this (*this_)
#define PRFX_(prfx,mid,name) prfx##mid##name
#define PRFX(prfx,mid,name) PRFX_(prfx,mid,name)
#define METHODS typedef struct CLASS CLASS; typedef struct {
#define BDATA } PRFX(CLASS,_,CVtbl); struct CLASS {CObj_CVtbl *vtbl_;
#define EDATA }; PRFX(CLASS,_,CVtbl) PRFX(CLASS,_,vtbl_); \
void PRFX(CLASS,_,dummy_)() {
#define METH(type, name, ...) } \
type PRFX(CLASS,_,name) (__VA_ARGS__); \
__attribute__((constructor)) void PRFX(CLASS,__init__,name)() { \
printf("initing %s\n", #name); \
PRFX(CLASS,_,vtbl_).name = &PRFX(CLASS,_,name); \
} \
type PRFX(CLASS,_,name) (__VA_ARGS__) { CLASS *this_ = gthis_;
#define MINIT(name) PRFX(CLASS,_,vtbl_).name = PRFX(CLASS,_,name)
#define CTOR } CLASS *PRFX(CLASS,_,init)(CLASS *o) \
{ o->vtbl_ = &PRFX(CLASS,_,vtbl_);
#define END }
#ifdef NOOP_IMPLEMENTATION
void *gthis_;
#endif
#endif