There is a fourth option, which I think might be optimal at this point:
to write a prolog API which under the hood calls the main executable and controls it through command line arguments passing and receiving data through stdin/stdout/stderr pipes. Most of the features of llama.cpp are exposed in the main executable. This solution has none of the disadvantages of the python interface and is much less work than the prolog wrapper or using the c ffi package. It also gives an opportunity for the prolog api to mature, and later on could be replaced with prolog wrappers. It is also a way to make something available to the community with which expertise can be gained in the new field. (btw, I used to think that using stdin/stout for interfaces was hacky until I did some work with erlang; they recommend most extensions to be done this way).