Home

C-macro-reflection-in-D

David Priver, July 30th, 2024

I was reading Hacker News when I saw the link to this article. I've been playing around with D lately and thought to myself "I bet D could do this as well". D added the ability to import C files (with macros) and has strong reflection capabilities as well.

So here is my attempt at that:

With a C file with macros:

// macros.c
// #include <Windows.h>
// just #define the macros here for simplicity
#define WM_A 0x1
#define WM_B 0x2
#define WM_C 0x3

And a D file to import the C file:

// imports the C file "macros.c"
import macros;
import std.stdio: writeln;
void print_macro(int num){
    switch(num){
        // compile time foreach so we can generate cases
        static foreach(m; __traits(allMembers, macros)){
            static if(m.length > 3 && m[0..3] == "WM_"){
                case __traits(getMember, macros, m):
                    writeln(m, ": ", num);
                    return;
            }
        }
        default:
            writeln("unknown macro: ", num);
            return;
    }
}

void main(){
    print_macro(0x1);
    print_macro(0x2);
    print_macro(0x3);
    print_macro(0x4);
}

Compile and run it:

$ ldc2 mac.d -of mac
$ ./mac
WM_A: 1
WM_B: 2
WM_C: 3
unknown macro: 4

All code in this article is released into the public domain.