我希望在很低的水平上处理数据。

因此,我有一个函数,该函数接收虚拟内存地址作为整数,并使用该内存地址“处理”。我从C接口(interface)了此函数,因此它的类型为(CUInt -> a)
我要链接的内存是文件中的Word8。可悲的是,我不知道如何访问该Word8的指针值。

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

最佳答案

为了简单的示例,假设您要向指针添加偏移量。

前置事项:

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 内部对Ptr进行withForeignPtr编码,但是文档警告您不要这样做:



代码很简单:
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')

09-10 19:41