Chr*_*non 11 memory haskell pointers
我希望在非常低的水平上操纵数据.
因此,我有一个函数,它接收一个虚拟内存地址作为一个整数和"做东西"与此内存地址.我从C接口这个函数,所以它有类型(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)
Run Code Online (Sandbox Code Playgroud)
是的,你写道你不想要的值Word8
,但我已经检索它peek
以证明指针是有效的.你可能会被诱惑return
的Ptr
,从里面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)
Run Code Online (Sandbox Code Playgroud)
要从Word8
您的问题中近似"a in a File",主程序将对文件进行内存映射,并使用该缓冲区来处理内存地址.
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)
Run Code Online (Sandbox Code Playgroud)
输出:
(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')