Как получить значение указателя в Haskell?

Я хочу управлять данными по очень низкому уровню.

Поэтому у меня есть функция, которая получает адрес виртуальной памяти, поскольку целое число и "действительно наполняет" этим адресом памяти. Я соединил интерфейсом с этой функцией от C, таким образом, это имеет тип (CUInt -> a). Память, которую я хочу связать, является a Word8 в файле. К сожалению, я понятия не имею, как получить доступ к значению указателя к этому Word8.

Чтобы быть ясным, мне не нужно значение Word8, мне нужно значение к адресу виртуальной памяти, который является значением указателя на него.

11
задан nbro 7 April 2017 в 13:09
поделиться

2 ответа

В качестве простого примера предположим, что вы хотите добавить смещение к указателю.

Передний вопрос:

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 , чтобы продемонстрировать, что указатель действует. У вас может возникнуть соблазн вернуть 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')
7
ответ дан 3 December 2019 в 10:03
поделиться

Вы, вероятно, ищете ptrToIntPtr и, возможно, fromIntegral , чтобы сделать его CUInt.

Обратите внимание, что CUInt не может представлять указатель на всех платформах.

3
ответ дан 3 December 2019 в 10:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: