我希望在非常低的水平上操纵数据。
因此,我有一个函数,它接收一个整数的虚拟内存地址,并用这个内存地址“做东西”。我从C接口此函数,因此它具有类型(CUInt -> a)
。
我要链接的内存是文件中的Word8
。遗憾的是,我不知道如何访问指向Word8
的指针值。
要清楚,我不需要Word8的值,我需要虚拟内存地址的值,这是指向它的指针的值。
答案 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不能代表所有平台上的指针。