With Emacs 28, you can get a file descriptor to a pipe process
and
send arbitrary data there (from arbitrary threads).
Cool, so that takes care of it.
You'd still need some small protocol (e.g. JSON) to
encode/decode
requests, but with that you can send arbitrary requests
back asynchronously.
I don't think you need a complex protocol: just stash somewhere
(inside
the module data structures) the data you need for the async
request,
then send a dummy byte to the pipe. On the Lisp side, just
install
a process-filter which calls back the module to "run any pending
async
requests".