C API malloc hassle

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..? :exploding_head:

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)

11 Likes

This is what I have been doing in my own apps as well, nice to see it become part of the SDK :smiley: also means we will get more accurate heap alloc data in the simulator by default!

1 Like

Oh my! No more _sbrk nightmare :partying_face:
That’s really awesome!!!

1 Like

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.

1 Like

Indeed, forgot that simulator also doesn't use setup.c. Implementing the calls in my own main.c results in the pd-realloc stuff being used.

1 Like

I wonder if something similar could be done for the file API.

I have these macros set which make it easier to port C libraries, but obviously not having to do this at all would be easiest. :slight_smile:

#define GKFile SDFile
#define kGKFileRead kFileRead
#define kGKFileReadData (kFileRead | kFileReadData)
#define kGKFileWrite kFileWrite
#define kGKFileAppend kFileAppend
#define kGKSeekSet 0
#define kGKSeekCurrent 1
#define kGKSeekEnd 2

#define GKFileOpen(path, mode) playdate->file->open((path), (mode))

#define GKFileClose(f) playdate->file->close((f))
#define GKFileSeek(f, position, whence) playdate->file->seek((f), (position), (whence))
#define GKFileRead(buffer, size, f) playdate->file->read((f), (buffer), (size))
#define GKFileWrite(buffer, size, f) playdate->file->write((f), (buffer), (size))
#define GKFileTell(f) playdate->file->tell((f))

playdate being a global pointer to the playdate object.

I'd take printf(...) too. :wink:

#define GKLog(...) playdate->system->logToConsole(__VA_ARGS__)

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

1 Like

I don't expect that would cause any problems, sure. I've filed that, should see it in the next release (after today's).

I could have sworn I did that, but I don't see it in there. Maybe I couldn't get the varargs to work right?