2010-03-05 54 views
9

我希望在非常低的水平上處理數據。如何在Haskell中獲取指針值?

因此,我有一個函數接收虛擬內存地址作爲一個整數和「做東西」這個內存地址。我從C接口這個函數,所以它的類型爲(CUInt -> a)。 我想鏈接的內存是文件中的Word8。可悲的是,我不知道如何訪問指向Word8的指針值。

要清楚,我不需要Word8的值,我需要虛擬內存地址的值,它是指向它的指針的值。

+0

你不能讓C中的函數取消引用指針? – kennytm 2010-03-05 12:30:39

回答

6

爲了一個簡單的例子,假設你想給指針添加一個偏移量。

前面的問題:

module Main where 
import Control.Monad (forM_) 
import Data.Char (chr) 
import Data.Word (Word8) 
import Foreign.ForeignPtr (ForeignPtr, withForeignPtr) 
import Foreign.Ptr (Ptr, plusPtr) 
import Foreign.Storable (peek) 
import System.IO.MMap (Mode(ReadOnly), mmapFileForeignPtr) 

是的,你寫的,你不希望Word8的價值,但我已經對peek檢索它表明指針是有效的。你也許會returnPtr從內withForeignPtr,但文檔警告不要說:

請注意,這不是安全地從動作返回指針和行動完成後使用它。指針的所有用途應位於withForeignPtr括號內。這種不安全的原因與下面的unsafeForeignPtrToPtr相同:終結器的運行時間可能比預期的要早,因爲編譯器只能跟蹤ForeignPtr對象的使用情況,而不能跟蹤由此產生的Ptr對象。

的代碼很簡單:

doStuff :: ForeignPtr Word8 -> Int -> IO() 
doStuff fp i = 
    withForeignPtr fp $ \p -> do 
    let addr = p `plusPtr` i 
    val <- peek addr :: IO Word8 
    print (addr, val, chr $ fromIntegral val) 

爲了接近從你的問題「的文件一Word8」,主程序內存映射文件,並使用該緩衝區做的東西與內存地址。

main :: IO() 
main = do 
    (p,offset,size) <- mmapFileForeignPtr path mode range 
    forM_ [0 .. size-1] $ \i -> do 
    doStuff p (offset + i) 
    where 
    path = "/tmp/input.dat" 
    mode = ReadOnly 
    range = Nothing 
-- range = Just (4,3) 

輸出:

(0x00007f1b40edd000,71,'G') 
(0x00007f1b40edd001,117,'u') 
(0x00007f1b40edd002,116,'t') 
(0x00007f1b40edd003,101,'e') 
(0x00007f1b40edd004,110,'n') 
(0x00007f1b40edd005,32,' ') 
(0x00007f1b40edd006,77,'M') 
(0x00007f1b40edd007,111,'o') 
(0x00007f1b40edd008,114,'r') 
(0x00007f1b40edd009,103,'g') 
(0x00007f1b40edd00a,101,'e') 
(0x00007f1b40edd00b,110,'n') 
(0x00007f1b40edd00c,33,'!') 
(0x00007f1b40edd00d,10,'\n')
3

您可能在尋找ptrToIntPtr或者fromIntegral以使其成爲CUInt。

請注意,雖然CUInt不能在所有平臺上表示指針。