Yes, it's possible to call Haskell code from C (and vice versa) through FFI, the Foreign Function Interface. Unfortunately, as the haskell.org docs says, you can't avoid the calls to initialize and finalize the haskell environment:
The call to hs_init() initializes GHC's runtime system. Do NOT try to
invoke any Haskell functions before calling hs_init(): bad things will
undoubtedly happen.
But, this is interesting also:
There can be multiple calls to hs_init(), but each one should be
matched by one (and only one) call to hs_exit()
And furthermore:
The FFI spec requires the implementation to support re-initialising
itself after being shut down with hs_exit(), but GHC does not
currently support that.
Basically my idea is that you may exploit this specifications in order to write youself a wrapper C++ class that manages the calls to hs_init
and hs_exit
for you, in example by using template methods surrounded by hs_init
and hs_exit
that you can override using any haskell call you want.
However, beware of interactions with other libraries calling haskell code: nested layers of calls to hs_init
and hs_exit
should be OK (so it's safe to use libraries which calls them in between your wrappers), but the total number of calls should always match, meaning that if those libraries only initialize the environment without trying to close it, then it's up to you to finish the job.
Another (probably better) idea, without exploiting inheritance and overriding, may be to have a simple class HaskellEnv
that calls hs_init
in the constructor and hs_exit
in the destructor. If you declare them as automatic variables, you'll obtain that the calls to hs_init
and hs_exit
will always be matched, and the latest call to hs_exit
will be made as soon as the latest HaskellEnv
object is destructed when you leave its scope.
Have a look at this question in order to prevent the creation of objects on the heap (they may be dangerous in this case).