I am not using C all that much, but when I do I notice that many APIs are using return parameters with a buffer and it's max size instead of returning a pointer to the requested buffer. Why is that, and more importantly - do I have to do that for every function I use only privately?
int crazy_c_getSomeText(char* buf, int len);
Yes; I think you are overseeing some memory management related things.
On top of my mind--and given my experience using .NET P/Invoke--I could say that, if I were to try to use a C API like the latter's signature in C#, I would most likely crash my application i.e., the "string" will be created in a location of memory my .NET Application may not have access to; any attempt to access the return value will cause problems. I think this is the case in many scenarios.
I believe it is not a good practice to assume the client of an API has access to the same portion of memory as the API itself.
Furthermore, in environments without automatic memory reclaiming (as is the case in C), every entity should "clean" after itself.
char* crazy_c_lib_getSomeText(); would not have such an option.