packages feed

libffi-0.1: examples/CTime.hsc

{-# LANGUAGE RankNTypes #-}
module Main where

#include <time.h>

import Foreign.C.Types
import Foreign.Ptr
import Foreign.Storable
import Foreign.Marshal
import Foreign.LibFFI
import Foreign.LibFFI.Base
import Foreign.LibFFI.FFITypes
import System.Posix.DynamicLinker

withDLCall :: String -> ((forall a. String -> RetType a -> [Arg] -> IO a) -> IO b) -> IO b
withDLCall lib f = do
    withDL lib [RTLD_NOW] $ \dl ->
        f $ \sym ret args -> do
                    p <- dlsym dl sym
                    callFFI p ret args

main = do
    withDLCall "" $ \call -> do
        t <- call "time" retCTime [argPtr nullPtr]

        with t $ \t_p -> do
                    tm_p <- call "localtime" (retPtr retVoid) [argPtr t_p]
                    tm <- peek (castPtr tm_p :: Ptr TM)
                    t' <- call "mktime" retCTime [argPtr tm_p]
                    print t
                    print tm
                    print t'

    withDLCall "./mytime.so" $ \call -> do
        t <- call "time" retCTime [argPtr nullPtr]

        -- struct tm actually has a few architecture dependent "hidden" fields...
        (argTM, retTM, freeTMType)
            <- newStorableStructArgRet $ replicate 9 ffi_type_sint ++ [ffi_type_slong, ffi_type_pointer]
            :: IO (TM -> Arg, RetType TM, IO ())

        tm <- call "mylocaltime" retTM [argCTime t]
        t' <- call "mymktime" retCTime [argTM tm]
        freeTMType
        print t
        print tm
        print t'

data TM = TM {sec, min, hour, mday, mon, year, wday, yday, isdst :: CInt}
    deriving (Eq, Show)

instance Storable TM where
        alignment _ = #{size int}
        sizeOf _ = #{size struct tm}
        peek p = do
                    sec <- #{peek struct tm, tm_sec} p
                    min <- #{peek struct tm, tm_min} p
                    hour <- #{peek struct tm, tm_hour} p
                    mday <- #{peek struct tm, tm_mday} p
                    mon <- #{peek struct tm, tm_mon} p
                    year <- #{peek struct tm, tm_year} p
                    wday <- #{peek struct tm, tm_wday} p
                    yday <- #{peek struct tm, tm_yday} p
                    isdst <- #{peek struct tm, tm_isdst} p
                    return $ TM sec min hour mday mon year wday yday isdst
        poke p (TM sec min hour mday mon year wday yday isdst) = do
                #{poke struct tm, tm_sec} p sec
                #{poke struct tm, tm_min} p min
                #{poke struct tm, tm_hour} p hour
                #{poke struct tm, tm_mday} p mday
                #{poke struct tm, tm_mon} p mon
                #{poke struct tm, tm_year} p year
                #{poke struct tm, tm_wday} p wday
                #{poke struct tm, tm_yday} p yday
                #{poke struct tm, tm_isdst} p isdst