开发者

How to get a pointer value in Haskell?

开发者 https://www.devze.com 2022-12-21 21:01 出处:网络
I wish to manipulate data on a very low level. Therefore I have a function that receives a virtual memory address as an integer and \"does stuff\" with this memory address. I interfaced this functio

I wish to manipulate data on a very low level.

Therefore I have a function that receives a virtual memory address as an integer and "does stuff" with this memory address. I interfaced this function from C, so it has the type (CUInt -> a). The memory I want to link is a Word8 in a file. Sadly, I have no idea how to access the pointer value to that Word8.

To be clear, I do not need the value of the Word8, i need the value to the virtual memory address, which is 开发者_JS百科the value of the pointer to it.


For the sake of a simple example, say you want to add an offset to the pointer.

Front matter:

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)

Yes, you wrote that you don't want the value of the Word8, but I've retrieved it with peek to demonstrate that the pointer is valid. You might be tempted to return the Ptr from inside withForeignPtr, but the documentation warns against that:

Note that it is not safe to return the pointer from the action and use it after the action completes. All uses of the pointer should be inside the withForeignPtr bracket. The reason for this unsafeness is the same as for unsafeForeignPtrToPtr below: the finalizer may run earlier than expected, because the compiler can only track usage of the ForeignPtr object, not a Ptr object made from it.

The code is straightforward:

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)

To approximate “a Word8 in a File” from your question, the main program memory-maps a file and uses that buffer to do stuff with memory addresses.

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)

Output:

(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')


You are probably looking for ptrToIntPtr and probably fromIntegral to make it a CUInt.

Note that a CUInt cannot represent a pointer on all platforms, though.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号