通过指针在Haskell数组到C函数
题
我有以下的C代码:
#include <sys/times.h>
#include <time.h>
float etime_( float *tarray )
{ struct tms buf;
times( &buf );
tarray[0] = 1.0 * buf.tms_utime / CLOCKS_PER_SEC;
tarray[1] = 1.0 * buf.tms_stime / CLOCKS_PER_SEC;
return tarray[0] + tarray[1];
}
试图端口这个Fortran代码到Haskell中:
PROGRAM Test
IMPLICIT NONE
REAL t, ta(2), etime
INTEGER i
DOUBLE PRECISION x
do i = 1, 10000
x = sin( cos( i * 1.0 d0 ) )
print *, x
enddo
ta(1) = 0.0d0
ta(2) = 0.0d0
t = etime( ta )
PRINT *, 'user time: ', ta(1)
PRINT *, 'system time: ', ta(2)
PRINT *, 'process time: ', t
END
如何定义阵列和!要么 !!!对于下面的代码工作?
module Main where
import GHC.Ptr
import GHC.Prim
import System.IO.Unsafe
import Control.Monad
foreign import ccall etime_ :: Ptr Double → IO Double
etime = etime_
main :: IO Int
main = do
mapM_ (print . sin . cos . (* (1.0 :: Double)) . fromIntegral) [1..10000 :: Int]
ta ← array 2
t ← etime ta
putStrLn $ "user time: " ++ show (ta !!! 0)
putStrLn $ "system time: " ++ show (ta !!! 1)
putStrLn $ "process time: " ++ show t
return 0
array :: Int → IO (Ptr a)
array size = undefined
(!) :: Ptr a → Int → IO a
(!) = undefined
(!!!) :: Ptr a → Int → a
(!!!) = undefined
解决方案
我建议这样的:
{-# LANGUAGE ForeignFunctionInterface #-}
import Foreign.Marshal.Array (allocaArray, peekArray)
import Foreign.Ptr (Ptr)
foreign import ccall etime_ :: Ptr Float -> IO Float
main :: IO ()
main = do
mapM_ (print . sin . cos . (* (1.0 :: Double)) . fromIntegral) [1..10000 :: Int]
allocaArray 2 $ \ta -> do
ptime <- etime_ ta
[utime, stime] <- peekArray 2 ta
putStrLn $ "user time: " ++ show utime
putStrLn $ "system time: " ++ show stime
putStrLn $ "process time: " ++ show ptime
但回答您的具体问题:
array :: Storable a => Int -> IO (Ptr a)
array = mallocArray
(!) :: Storable a => Ptr a -> Int -> IO a
(!) = peekElemOff
(!!!) :: Storable a => Ptr a -> Int -> a
(!!!) ptr = unsafePerformIO . peekElemOff ptr
我建议使用hoogle找到你所需要的功能。
其他提示
返回的总和,用户时间,并作为一个元组的系统时间。需要注意的是ETIME需要一个指针浮动,而不是增加一倍,这样会让你的类型保持一致:
{-# LANGUAGE ForeignFunctionInterface #-}
module Main where
import Foreign (Ptr)
import Foreign.Marshal.Array (allocaArray,peekArray)
import Control.Monad (mapM_)
foreign import ccall etime_ :: Ptr Float -> IO Float
etime :: IO (Float, Float, Float)
etime = do
allocaArray 2 $ \ta -> do
t <- etime_ ta
[user,sys] <- peekArray 2 ta
return (t,user,sys)
main :: IO Int
main = do
mapM_ (print . sin . cos . (* (1.0 :: Double)) . fromIntegral) [1..10000 :: Int]
(t,user,sys) <- etime
putStrLn $ "user time: " ++ show user
putStrLn $ "system time: " ++ show sys
putStrLn $ "process time: " ++ show t
return 0
鉴于以下附加的Haskell模块:
module AllocSymbols (
(↑≣), -- mallocArray
(≣⊠), -- free
(≣→), -- peekElemOff
(≣←), -- pokeElemOff
(⥱), -- peekElemOff unsafe
(⥅), -- advancePtr
) where
import GHC.Ptr
import System.IO.Unsafe
import Foreign.Storable
import Foreign.Marshal.Alloc (free)
import Foreign.Marshal.Array
(↑≣) :: Storable a ⇒ Int → IO (Ptr a)
(↑≣) = mallocArray
(⥱) :: Storable a ⇒ Ptr a → Int → a
a ⥱ i = unsafePerformIO $ peekElemOff a i
(≣→) :: Storable a ⇒ Ptr a → Int → IO a
(≣→) = peekElemOff
(≣←) :: Storable a ⇒ Ptr a → Int → a → IO ()
(≣←) = pokeElemOff
(⥅) :: Storable a ⇒ Ptr a → Int → Ptr a
(⥅) = advancePtr
(≣⊠) :: Ptr a → IO ()
(≣⊠) = Foreign.Marshal.Alloc.free
现在我们可以端口这块Fortran代码:
PROGRAM Test
IMPLICIT NONE
REAL t, ta(2), etime
INTEGER i
DOUBLE PRECISION x
do i = 1, 10000
x = sin( cos( i * 1.0 d0 ) )
print *, x
enddo
ta(1) = 0.0d0
ta(2) = 0.0d0
t = etime( ta )
PRINT *, 'user time: ', ta(1)
PRINT *, 'system time: ', ta(2)
PRINT *, 'process time: ', t
END
逐字逐句到Haskell的:
module Main where
import GHC.Ptr
import AllocSymbols
import Control.Monad
foreign import ccall etime_ :: Ptr Float → IO Float
main :: IO ()
main = do
mapM_ (print . sin . cos . (* (1.0 :: Double)) . fromIntegral) [1 .. 10000 :: Int]
ta ← (2 ↑≣) -- ta :: Ptr Float
(ta ≣← 0) 0.0
(ta ≣← 1) 0.0
t ← etime_ ta
putStrLn $ " user time: " ++ show (ta ⥱ 0)
putStrLn $ " system time: " ++ show (ta ⥱ 1)
putStrLn $ " process time: " ++ show t
(ta ≣⊠) -- optional in this case
不隶属于 StackOverflow