我希望在非常低的水平上处理数据。如何在Haskell中获取指针值?
因此,我有一个函数接收虚拟内存地址作为一个整数和“做东西”这个内存地址。我从C接口这个函数,所以它的类型为(CUInt -> a)
。 我想链接的内存是文件中的Word8
。可悲的是,我不知道如何访问指向Word8
的指针值。
要清楚,我不需要Word8的值,我需要虚拟内存地址的值,它是指向它的指针的值。
我希望在非常低的水平上处理数据。如何在Haskell中获取指针值?
因此,我有一个函数接收虚拟内存地址作为一个整数和“做东西”这个内存地址。我从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)
是的,你写的,你不希望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)
为了接近从你的问题“的文件一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')
您可能在寻找ptrToIntPtr或者fromIntegral以使其成为CUInt。
请注意,虽然CUInt不能在所有平台上表示指针。
你不能让C中的函数取消引用指针? – kennytm 2010-03-05 12:30:39