What is the proper/preferred way to allocate memory in a C API?
I can see, at first, two options:
1) Let the caller do all the (outer) memory handling:
myStruct *s = malloc(sizeof(s));
myStruct_init(s);
myStruct_foo(s);
myStruct_destroy(s);
free(s);
The _init and _destroy functions are necessary since some more memory may be allocated inside, and it must be handled somewhere.
This has the disadvantage of being longer, but also the malloc can be eliminated in some cases (e.g., it can be passed a stack-allocated struct:
int bar() {
myStruct s;
myStruct_init(&s);
myStruct_foo(&s);
myStruct_destroy(&s);
}
Also, it’s necessary for the caller to know the size of the struct.
2) Hide mallocs in _init and frees in _destroy.
Advantages: shorter code, since the functions are going to be called anyway. Completely opaque structures.
Disadvantages: Can’t be passed a struct allocated in a different way.
myStruct *s = myStruct_init();
myStruct_foo(s);
myStruct_destroy(foo);
I’m currently leaning for the first case; then again, I don’t know about C API design.
My favourite example of a well-design C API is GTK+ which uses method #2 that you describe.
Although another advantage of your method #1 is not just that you could allocate the object on the stack, but also that you could reuse the same instance multiple times. If that’s not going to be a common use case, then the simplicity of #2 is probably an advantage.
Of course, that’s just my opinion 🙂