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.