void type_init(type *t, [...]);
void type_clear(type *t, [...]);
This is essentially explicit constructors and destructors in C, and one can legitimately argue that it is clunky, verbose and error-prone.However, if we are constrained to a C API, it does have one important practical quality in my experience: Because it is always the same, it eases the mental load on both the API's user and the API's implementer, especially if there are many such types involved.
[1] See e.g. https://gmplib.org/manual/Initializing-Integers