The presence of the explicit struct; the necessity of manual assignment of values (as opposed to implicit capture); manual management of the memory involved: none of these can make functional-style code so ugly as the mere fact that Cís syntax provides no device for writing functions anonymously and inline.
Once you combine the latter fact with the faults you mention, you inevitably run into a curious equivalence. Structs with function pointers; to functions written out of line; which accept a pointer to a user data struct: does that not sound oddly familiar? It should: there is no decidable distinction between writing OO-style C and functional-style C. Both involve the exact same mechanics of construction.
Makeshifts last the longest.