> "Abstractions are useful until they're not."
So, I thought this was going to be an easy issue. But alas, it is far from it with my current C lang skills.
I started out with some easy example to follow, and moved stuff around as I saw fit.
```
#include <SDL3/SDL_init.h>
#define SDL_MAIN_USE_CALLBACKS 1
SDL_AppResult SDL_AppInit(void** appstate, int argc, char* argv[]) { // Stuff return SDL_APP_CONTINUE; }
SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event) { // Stuff return SDL_APP_CONTINUE; }
SDL_AppResult SDL_AppIterate(void* appstate) { // Stuff return SDL_APP_CONTINUE; }
void SDL_AppQuit(void* appstate, SDL_AppResult result) { }
```
Instead of using a regular `main()`, SDL3 provides this callback pattern which more or less hides its own `main()`, overrides it and performs some magic to become platform agnostic, while passing around `appstate`.
From the get-go, this looks pretty simple and it is.
But I'm not too fond of the abstraction. The callback system forces a `void* appstate` through every callback, which means heap allocation if you want to pass both an `Engine` and a `Game` struct around. You end up with a wrapper struct, `calloc`, pointer casting on every callback, and manual cleanup. For two structs that could live on the stack.
More importantly, the event loop is hidden inside SDL's callback dispatcher. I can't see the `while(running)` loop. I can't set a breakpoint at frame boundaries. For someone learning C, not seeing the control flow means I'm trusting an abstraction I don't fully understand yet.
So I want to roll my own `main()`, to become more versatile in C as a whole.
Here's the thing though: according to the SDL3 documentation, you can still write a standard `int main()` and reap the benefits of SDL3 handling platform-specific entry points (like `WinMain` on Windows).
You just include `<SDL3/SDL_main.h>` and write your own loop. SDL still intercepts at link time and routes platform-specific entry points to your `main()`.
The difference is that you own the event loop, the polling, and the lifecycle — which is the whole idea behind this project.
This will be an ongoing task for a while, to rewrite `main` and refactor some other components to make it easier and _keep it simple, stupid_.
No final code to show yet. This is the messy middle. Next post will have the results.
---
_Transparency note: I use Lumo as a technical reviewer for these posts — checking C semantics, verifying claims, and catching formatting issues. The ideas, mistakes, and fixes are my own._