4

I have a C function that creates a null terminated string and returns a pointer to it, there is also corresponding deallocation function.

foreign import ccall unsafe "get_str" getStr :: IO CString
foreign import ccall unsafe "free_str" freeStr :: CString -> IO ()

I want to create a Haskell String from the returned CString, and free CString as soon as possible.

do cStr <- getStr
   str <- peekCString cStr
   freeStr cStr
   -- here str is used

Is it safe to free cStr before str is used? In other words, does peekCString create Haskell String all at once, or is it created lazily?

Don Stewart
  • 137,316
  • 36
  • 365
  • 468
robson3.14
  • 3,028
  • 2
  • 20
  • 19

1 Answers1

7

peekCString is strict -- it doesn't suspend the loop via unsafeInterleaveIO, for example, so once you have the head of the string, you've definitely already computed the tail. Here's the implementation:

peekCAString cp = do
  l <- lengthArray0 nUL cp
  if l <= 0 then return "" else loop "" (l-1)
  where
    loop s i = do
        xval <- peekElemOff cp i
        let val = castCCharToChar xval
        val `seq` if i <= 0 then return (val:s) else loop (val:s) (i-1)
Don Stewart
  • 137,316
  • 36
  • 365
  • 468
  • If I have a C function which has no side effects and returns strings, can I fool Haskell into thinking that `getStr >>= peekCString` is not an `IO String`, but rather a `String`? It is declared as `peekCString :: CString -> IO String` at http://hackage.haskell.org/package/base-4.7.0.2/docs/src/Foreign-C-String.html#peekCString – imz -- Ivan Zakharyaschev Feb 12 '15 at 13:49