Tm_api_registry_api returns a "struct full of NULL function pointers?" How?

The API Registry states that calling get() on an API that hasn’t been loaded yet will return a “struct full of NULL function pointers”, and that when the API is eventually loaded these NULL function pointers will be “replaced by the real function pointers of the API.”

This stumped me for a while. How can a function return a “struct of NULL function pointers”? The only thing I could think of is that get() probably memsets some memory to zero and returns that. After all, the API structs are purely abstract and full of function pointers that lend themselves well to getting initialized to zero.

Assuming that’s the trick, I’m curious… how on earth does the API registry know how MUCH memory to memset and zero? The API registry has no idea (yet) how big any of the API structs that will be loaded will be!

In other words, if the first thing I do is ask the API Registry to get() an API, and the only thing I pass it is the name of the API, how does API registry know how much memory to allocate and zero in order to return it?

Sorry if it’s a nosey question, but this part of the design really struct me and now I’m super curious. The set() function passes in bytes, but that hasn’t been called yet! That’s not called until the DLL loads!

Only thing I can think of is that a its a large hardcoded number and that once the API is set the memory is realloc’d down to the appropriate size. Or maybe it’s more elegant than that. I probably would have just passed the size with the get() function and used that to know how much to return if it’s not ready yet.

Hi mdeforge,

I believe it’s as you guessed, they allocate a chunk of fixed-sized memory that’s likely to be “large enough”, say 8KB, that’s 1024 function pointers and unlikely to cause a problem. It’s simple and makes for a nicer API user-experience. If they want to be fancy and catch anyone writing outside of that 8KB of memory they could allocate it at the end of a page and mark the next page readonly which would triggered a memory access violation.

Something related that’s kind of a “dirty but simple” thing is that during plugin reloads they don’t release the old plugin because they keep pointers to various bits of data in the old plugin’s memory space, for example registered editor ui text.

We’ll see if @niklas or @tobias can shed some light on it :slight_smile:


1 Like

Yup, that’s exactly what we do.

But we also actually check that we did allocate a large enough memory chunk in the tm_api_registry->set() call. I.e., we check that bytes is smaller than the fixed memory chunk we allocate.


Amazing, thank you for shedding some light on that. Brilliant!