Skip to content

Instantly share code, notes, and snippets.

@brimonk
Created November 30, 2021 06:47
Show Gist options
  • Save brimonk/5f7c6258f855c57c886c37177ada20c3 to your computer and use it in GitHub Desktop.
Save brimonk/5f7c6258f855c57c886c37177ada20c3 to your computer and use it in GitHub Desktop.
A Small, Metaprogramming Example in C
// Brian Chrzanowski
// 2021-11-30 00:06:44
//
// This is just a small demonstration that with the help of the C Preprocessor, and some macros, we
// can approach some meta programming things that get compile-time checked by the compiler. It isn't
// as elegant as something like Jai, but in theory, you could execute something like this at the
// very start of the program.
//
// If C supported more things out of the box to facilitate metaprogramming, this could could get a
// lot nicer, but that's what it is.
//
// OUTPUT:
// metadata:
// size: 12
// fields: 3
//
// name: i
// size: 4
// type: int
// offset: 0
// name: j
// size: 4
// type: int
// offset: 4
// name: k
// size: 4
// type: int
// offset: 8
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#define NameOf(x) (#x)
#define MemberSize(type, member) sizeof(((type *)0)->member)
// TestStruct : this is the actual struct you might have in the program as some "data".
struct TestStruct {
int i, j, k;
};
// Field : defines a single field, within a structure
// NOTE (Brian): You could reasonably create a mapping between the text type and some enum
// for easier mangling in the future.
struct Field {
char name[32];
char type[64];
int size;
int offset;
};
// Structure : this is the metadata for a single structure
struct Structure {
char *name;
int size;
struct Field fields[64];
int cnt;
};
#define ADDMETA(m,s,t,y) AddMeta(m, NameOf(y), NameOf(t), MemberSize(s,y), offsetof(s,y))
void AddMeta(struct Structure *meta, char *name, char *type, int size, int offset)
{
struct Field *field;
if (meta && meta->cnt < 64) {
field = meta->fields + meta->cnt++;
strncpy(field->name, name, sizeof(field->name));
strncpy(field->type, type, sizeof(field->type));
field->size = size;
field->offset = offset;
}
}
int main(int argc, char **argv)
{
struct Structure metadata;
int i;
memset(&metadata, 0, sizeof metadata);
metadata.name = NameOf(struct Structure);
metadata.size = 0;
ADDMETA(&metadata, struct TestStruct, int, i);
ADDMETA(&metadata, struct TestStruct, int, j);
ADDMETA(&metadata, struct TestStruct, int, k);
for (i = 0; i < metadata.cnt; i++) {
metadata.size += metadata.fields[i].size;
}
printf("metadata:\n");
printf("\tsize: %d\n", metadata.size);
printf("\tfields: %d\n", metadata.cnt);
printf("\n");
for (i = 0; i < metadata.cnt; i++) {
printf("\tname: %s\n", metadata.fields[i].name);
printf("\t\tsize: %d\n", metadata.fields[i].size);
printf("\t\ttype: %s\n", metadata.fields[i].type);
printf("\t\toffset: %d\n", metadata.fields[i].offset);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment