With maybe some default options should be enough for at least the basics.
Note that the indirection overhead would be significant, but without generics or something similar, you don't really have a choice.
The problem here is *void, which is not great. You lose type safety with this approach, and the allocation problems are still present. Rolling your own can be both more type safe and better suited to your problem area, and it's not particularly difficult.
What about a use case where you want to use a hashmap to store 3 different types of keys independently. Would you implement the hashmap once and just store a union of the 3 types and then assert the correct type has been stored at each call site? Would you implement the hash map 3 different times? What happens if later on, some years later, the code needs to change and another type needs to be stored in a map? Generalizing a map via void pointers is the most pragmatic solution.
It depends on your specific needs and is difficult to characterize in hypothetical. I imagine that it would probably involve Hare's native tagged unions, though.