Haskell FFI how to take an address of the local value

ffi, haskell

Solution

I was able to do:

import Foreign.C.String
import Foreign.Marshal.Alloc

-- Your declarations and foreign bindings here

getTime :: IO String
getTime = do
    p <- malloc
    c_time p
    tmPtr <- c_localtime p
    str <- peekCString $ c_asctime tmPtr
    free p
    return str

main :: IO ()
main = do
    currentTime <- getTime
    putStrLn currentTime

The key is using `malloc` and `free`, you explicitly allocate the space, pass it to `c_time` to set the contents, then `c_localtime` to format it as a `CTmStruct`, then pass that to `c_asctime` to convert to a `CString`, marshal back to a Haskell `String` with `peekCString`, and finally free the pointer used to get the time.

I guess I should have realized this sooner, but a better solution would be to use `alloca`:

getTime :: IO String
getTime = alloca $ \p -> do
    c_time p
    tm <- c_localtime p
    peekCString $ c_astime tm

Which is safer, shorter, and easier. The `alloca` function does the allocation and freeing of the pointer for you, all you have to do is use it.

Problem

I try to work with this simple C-code from Haskell: ``` time_t rawTime = time( NULL ); struct tm* timeInfo = localtime( &rawTime ); /* Using address of a local variable */ printf( "The current date is: %s", asctime( timeInfo ) ); ``` So I write: ``` data CTmStruct = CTmStruct type CTmStructPtr = Ptr CTmStruct foreign import ccall "time" c_time :: Ptr CTime -> IO CTime foreign import ccall "localtime" c_localtime :: Ptr CTime -> IO CTmStructPtr foreign import ccall "asctime" c_asctime :: CTmStructPtr -> CString main :: IO () main = do rawTime <- c_time nullPtr tmStructPtr <- c_localtime ??? -- How to get an address of rawTime? print $ c_asctime tmStructPtr ``` So how can I get an address of a local value `rawTime` for putting it as an argument of a `c_localtime` function? I've read documentation to `Foreign` module, but I didn't find answer for this question. I'd be very grateful for any help.

Original source