Question

Good day!

The core of my project is written inside ST monad and I am trying to add some features that were implemented in C. I've implemented the FFI for all functions that I need:

foreign import ccall unsafe "codec/encode.h encode_symbol"
    encodeSymbol :: Ptr EncodingEnv
                 -> CShort            -- symbol to encode
                 -> Ptr Context
                 -> IO ()

Both Context and EncodingEnv are modified inside the C routine. I have working Storable instances for both EncodingEnv and Context. The simple main test program works well.

Nonetheless, all of the code that need to call these C routines lays inside the ST monad. I need to store these Ptrs to EncodingEnv and to Context somewhere.

How should I deal with long-lived mutable C structures inside the ST monad and how do I call these C routines? My suggestion is to use STRef (Foreign?Ptr Context), but how do I malloc these pointers from ST? I fail to find it in any examples or tutorials.

Thank you

Was it helpful?

Solution

The ST monad is really intended for working with Haskell-allocated state like STRef and STArray.

If the things you want to call out to don't have externally visible side-effects and just manipulate the structures you'll be passing them, it's probably "morally" ok to use unsafeIOToST to call them.

You'll need to take care that you don't let your pointers escape the specific ST computation they are used in as you won't get the normal safety benefits guaranteed by the phantom s parameter to ST.

Using STRef (ForeignPtr ...) won't really help in itself, but perhaps you might use a newtype wrapper that uses the phantom type parameter s to give a little extra self-imposed safety.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top