2010-03-05 97 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不能在所有平台上表示指针。