Haskell FFI如何取一个本地值的地址

时间:2014-03-24 20:22:14

标签: haskell ffi

我尝试使用来自Haskell的这个简单的C代码:

time_t rawTime = time( NULL );
struct tm* timeInfo = localtime( &rawTime );  /* Using address of a local variable */
printf( "The current date is: %s", asctime( timeInfo ) );

所以我写道:

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

那么如何才能获得本地值rawTime的地址,以便将其作为c_localtime函数的参数?我已经阅读了Foreign模块的文档,但我没有找到这个问题的答案。我会非常感谢任何帮助。

1 个答案:

答案 0 :(得分:3)

我能够做到:

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

关键是使用mallocfree,您明确分配空间,将其传递给c_time以设置内容,然后c_localtime将其格式化为{ {1}},然后将其传递给CTmStruct以转换为c_asctime,使用CString封送回Haskell String,最后释放用于获取时间。


我想我应该早点意识到这一点,但更好的解决方案是使用peekCString

alloca

哪个更安全,更短,更容易。 getTime :: IO String getTime = alloca $ \p -> do c_time p tm <- c_localtime p peekCString $ c_astime tm 函数为你分配和释放指针,你所要做的就是使用它。