如何在Haskell中获取指针值?

时间:2010-03-05 11:06:48

标签: memory pointers haskell

我希望在非常低的水平上操纵数据。

因此,我有一个函数,它接收一个整数的虚拟内存地址,并用这个内存地址“做东西”。我从C接口此函数,因此它具有类型(CUInt -> a)。 我要链接的内存是文件中的Word8。遗憾的是,我不知道如何访问指向Word8的指针值。

要清楚,我不需要Word8的值,我需要虚拟内存地址的值,这是指向它的指针的值。

2 个答案:

答案 0 :(得分:7)

为了一个简单的例子,假设你想为指针添加一个偏移量。

前面的事情:

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检索它以证明指针有效。您可能会return来自withForeignPtr内的Ptr,但文档警告说:

  

请注意,从操作返回指针并在操作完成后使用它是不安全的。指针的所有用法都应在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')

答案 1 :(得分:3)

您可能正在寻找ptrToIntPtr,可能还需要fromIntegral才能使其成为CUInt。

请注意,CUInt不能代表所有平台上的指针。