2010-03-05 17 views
9

Ich möchte Daten auf einem sehr niedrigen Niveau manipulieren.Wie bekomme ich einen Zeigerwert in Haskell?

Daher habe ich eine Funktion, die eine virtuelle Speicheradresse als Integer erhält und mit dieser Speicheradresse "stopft". Ich habe diese Funktion von C aus angebunden, also hat sie den Typ (CUInt -> a). Der Speicher, den ich verknüpfen möchte, ist eine Word8 in einer Datei. Leider habe ich keine Ahnung, wie man auf den Zeigerwert zu diesem Word8 zugreift.

Um klar zu sein, brauche ich nicht den Wert von Word8, ich brauche den Wert der virtuellen Speicheradresse, die der Wert des Zeigers ist.

+0

Können Sie nicht eine Funktion in C zu dereferenzieren den Zeiger machen? – kennytm

Antwort

6

Um ein einfaches Beispiel zu nennen, sagen Sie, dass Sie einen Offset zum Zeiger hinzufügen möchten.

Titelei:

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) 

Ja, schrieben Sie, dass Sie den Wert des Word8 nicht wollen, aber ich habe es abgerufene mit peek zu zeigen, dass der Zeiger gültig ist. Sie könnten die Ptr von innen withForeignPtr, aber die Dokumentation warnt vor, dass zu return versucht sein:

Beachten Sie, dass es nicht sicher ist, den Zeiger von der Aktion zurückzukehren und es zu verwenden, nachdem die Aktion abgeschlossen ist. Alle Verwendungen des Zeigers sollten innerhalb der withForeignPtr Klammer sein. Der Grund für diese Unsicherheit ist derselbe wie für unsafeForeignPtrToPtr: Der Finalizer kann früher als erwartet ausgeführt werden, da der Compiler nur die Verwendung des Objekts ForeignPtr verfolgen kann, kein Objekt Ptr, das daraus hergestellt wurde.

Der Code ist unkompliziert:

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) 

zu nähern „um ein Word8 in einer Datei“ aus Ihrer Frage, die Haupt-Programmspeicher-Karten eine Datei und verwendet diesen Puffer Material mit Speicheradressen zu tun.

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) 

Ausgang:

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

Sie suchen wahrscheinlich nach ptrToIntPtr und wahrscheinlich fromIntegral, um es zu einem CUInt zu machen.

Beachten Sie, dass ein CUInt keinen Zeiger auf allen Plattformen darstellen kann.

Verwandte Themen