I was adding a section to the docs about why we have to jump through pd->system->realloc instead of calling malloc() directly, and included macros to hide it away:
PlaydateAPI* pd; // global, must be set at load time
#define malloc(size) pd->system->realloc(NULL,size)
#define realloc(ptr,size) pd->system->realloc(ptr,size)
#define free(ptr) pd->system->realloc(ptr,0)
and Marc pointed out that if I made those functions instead it would still work and malloc() calls in the game would call those instead of the newlib versions. Whoa. I guess I'd thought they would conflict instead of ours overriding newlib? I poked around some more and discovered that if we instead implement that at _malloc_r() etc. then printf() will also use our allocator instead of giving the dreaded _sbrk error. I added this to setup.c, and it seems to work fine..?
I'll get this into 1.10, but if you want to test it out now, here's the updated C_API/buildsupport/setup.c: setup.c.zip (1.0 KB)
This is what I have been doing in my own apps as well, nice to see it become part of the SDK also means we will get more accurate heap alloc data in the simulator by default!
Actually.. in the simulator those malloc calls will go straight to the system malloc and we won't be able to track them. Hopefully there's some way to tell the loaders to resolve malloc calls in the pdex.dylib/so/dll to our version.
Can I request adding support for the .__init section? It requires only modifying setup.c to call __init/__fini as described here: [CPP] Guide: C++ on Playdate -- this is nice because even in C sometimes libraries and code expects .__init to work, such as when using __attribute__((constructor)).
It would also be nice (but less pressing) to add the C++ exception frame symbols to the linker map: [CPP] Guide: C++ on Playdate
Bumbled into this because a library I'm pulling in uses calloc instead of malloc, and setup.c doesn't override that one. That didn't work well on device, or in the simulator with the 16MB malloc pool enabled. Since the library already has its own alias to calloc, I just redefined that alias to hit my own "pdcalloc" instead of calloc, where pdcalloc just calls malloc (which in turn calls pdrealloc) and memset. This fixes everything but it's not really the most beautiful approach to mess with a library that I don't own and I might want to take updates to someday.
Would it be worthwhile for setup.c to handle calloc as well?
Is there a more elegant way to do this in my project, outside the library? Just directly redefining calloc in my glue code that gets built before Chipmunk works in the simulator, but not on device:
Presumably that's because there's a _calloc_r that's what I have to redefine if TARGET_PLAYDATE (along the lines of _malloc_r et al) but that stuff has extra entanglements that look a bit above my paygrade. I've lost what little C/C++ fluency I had years ago, and am really in a banging-rocks-together mode.
Oh yeah. Nice catch. Like I said, banging rocks together. I didn't even write the method, I stole it from @maximile's old Chipmunk Playdate demo. I'm lucky that putting together Lua bindings for a C library doesn't take a tremendous level of virtuosity.