--- /dev/null
+test: main.c closure.c closure.h player.c player.h
+ cc -g main.c closure.c player.c -o test -Wall -Wextra
--- /dev/null
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include "closure.h"
+
+typedef struct __attribute__((packed)) {
+ uint16_t opcode_0;
+ void *operand_0;
+
+ uint16_t opcode_1;
+ void *operand_1;
+
+ uint16_t opcode_2;
+} Closure;
+
+// rdi, rsi, rdx, rcx, r8, r9
+static const uint16_t mov[6] = {0xbf48, 0xbe48, 0xba48, 0xb948, 0xb849, 0xb949};
+static size_t size;
+
+__attribute__((constructor)) static void init()
+{
+ size = sysconf(_SC_PAGESIZE);
+}
+
+void *closure_create(void *self, ClosureParam *param, size_t num)
+{
+ Closure *block = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
+
+ for (size_t i = 0; i < num; i++) {
+ if (param[i].arg > 6)
+ abort(); // TODO
+
+ block[i].opcode_0 = 0xb848;
+ block[i].operand_0 = param[i].fun;
+
+ block[i].opcode_1 = mov[param[i].arg];
+ block[i].operand_1 = self;
+
+ block[i].opcode_2 = 0xe0ff;
+
+ *((void **) param[i].ptr) = &block[i];
+ }
+
+ mprotect(block, size, PROT_READ | PROT_EXEC);
+ return block;
+}
+
+void closure_destroy(void *closure)
+{
+ munmap(closure, size);
+}
--- /dev/null
+#ifndef _CLOSURE_H_
+#define _CLOSURE_H_
+
+typedef struct {
+ void *fun;
+ void *ptr;
+ unsigned int arg;
+} ClosureParam;
+
+void *closure_create(void *self, ClosureParam *params, size_t num);
+void closure_destroy(void *closure);
+
+#endif
--- /dev/null
+#include <stdio.h>
+#include "player.h"
+
+int main()
+{
+ Player *p1 = player("Fleckenstein");
+ p1->age = 16;
+
+ Player *p2 = player("lizzy22");
+ p2->age = 22;
+
+ p1->print();
+ printf("age diff = %d; adult = %d\n", p1->compare(p2), p1->adult());
+
+ for (int i = 0; i < 10; i++)
+ p1->birthday();
+
+ printf("age diff = %d; adult = %d\n", p1->compare(p2), p1->adult());
+
+ p1->delete();
+ p2->delete();
+}
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include "closure.h"
+#include "player.h"
+
+static bool player_adult(Player *self)
+{
+ return self->age >= 18;
+}
+
+static void player_print(Player *self)
+{
+ printf("Name: %s\nAge: %d\n", self->name, self->age);
+}
+
+static void player_birthday(Player *self)
+{
+ self->age++;
+}
+
+static int player_compare(Player *other, Player *self)
+{
+ return self->age - other->age;
+}
+
+static void player_delete(Player *self)
+{
+ closure_destroy(self->closure);
+ free(self);
+}
+
+Player *player(char *name)
+{
+ Player *self = malloc(sizeof *self);
+ self->name = name;
+ self->age = 0;
+
+ self->closure = closure_create(self, (ClosureParam[5]) {
+ {&player_adult, &self->adult, 0},
+ {&player_print, &self->print, 0},
+ {&player_birthday, &self->birthday, 0},
+ {&player_compare, &self->compare, 1},
+ {&player_delete, &self->delete, 0},
+ }, 5);
+
+ return self;
+}
--- /dev/null
+#ifndef _PLAYER_H_
+#define _PLAYER_H_
+
+#include <stdbool.h>
+
+typedef struct Player {
+ int age;
+ char *name;
+
+ void *closure;
+ bool (*adult)();
+ void (*print)();
+ void (*birthday)();
+ int (*compare)(struct Player *other);
+ void (*delete)();
+} Player;
+
+Player *player(char *name);
+
+#endif