Passing a pointer to a state object around is probably the best solution. Why?
The statefulness of your functions is made explicit and obvious.
It is the most general and most extensible solution.
Unfortunately, APIs with a (hidden) global state are fairly common. They tend to make simple things simpler, but often make more difficult things outright impossible.
E.g. imagine a database client library. To access a database, you need to create a connection first. What happens if I want to connect to multiple databases at the same time? If there is a single global connection hidden in the library, this is outright impossible.
Passing an extra parameter around is somewhat annoying. But as long as all the state is grouped into a single object that has to be carried around, it isn't very annoying.
Even if I would decide to keep a hidden global state, I would group that state into a single object so that it becomes easier to manage. Keeping track of multiple related global variables is quite error-prone, checking whether a single global variable has been initialized is much easier. Note that with a hidden global state, you will have to check whether the state is set in each exported function in order to prevent user errors.