Hogyan csináljunk kékhalált Haskell-ben?

Haskell I/O rendszer

A Haskell I/O rendszere tisztán funkcionális, mégis tartalmazza azokat a lehetőségeket, amelyeket a hagyományos programozási nyelvek kínálnak. Az imperatív nyelvekben a programok műveletek sorozataként haladnak, amelyek vizsgálják és módosítják a világ aktuális állapotát.

Haskell I/O rendszere egy matematikai alapokon nyugvó fogalomra, a monádra épül. Az I/O monádot célszerű egy absztrakt adattípusként kezelni.

Az akciók Haskellben definiálva vannak, de nem közvetlenül végrehajtva. Az akciók végrehajtása a Haskell kifejezések kiértékelésén kívül történik.

Haskell mutatók (Ptr) és dinamikus memória

A Foreign modul biztosítja a Ptr típust, amely a Haskellben a C-szerű mutatók kezelésére szolgál.

  • malloc / mallocBytes: Memóriafoglalás típus vagy bájtméret alapján.
  • calloc / callocBytes: Nullázott memóriafoglalás.
  • alloca: Automatikus ideiglenes memóriafoglalás.
  • allocaBytes: Memória méret kézi megadása bájtban.
  • allocaBytesAligned: Igazított memóriaterület.

Példa malloc használatára:

import Foreign
import Foreign.C

allocateInt :: IO (Ptr CInt)
allocateInt = malloc

main :: IO ()
main = do
    ptr <- allocateInt
    poke ptr 42
    value <- peek ptr
    print value
    free ptr

Ebben a példában lefoglalunk egy CInt típusú memóriaterületet, értéket írunk és olvasunk belőle, majd felszabadítjuk.

C típusok Haskellben

C típus – Haskell típus táblázat
C és Haskell típusok összehasonlítása
C típus Haskell típus Leírás
intCIntEgész szám
unsigned intCUIntElőjelnélküli egész
charCCharKarakter
void*Ptr ()Általános mutató
A*Ptr aTetszőleges típusra mutató pointer
A****Ptr (Ptr (Ptr (Ptr a)))Négy szint mély pointer

Windows API és az ntdll.dll

A Windows operációs rendszer különböző API-hívásokkal vezérelhető. Az ntdll.dll könyvtár alacsony szintű rendszerhívásokat tartalmaz.

RtlAdjustPrivilege

Ez a függvény egy adott jogosultság engedélyezésére vagy letiltására szolgál. A Privilege paraméter 19-re állításával a SeShutdownPrivilege jogosultságot engedélyezi.

RtlAdjustPrivilege paraméterek ábrája

NtRaiseHardError

Ez egy dokumentálatlan függvény, amely az ntdll.dll könyvtárban található. A ErrorStatus paraméter megadásával kékhalált idézhet elő.

NtRaiseHardError paraméterek ábrája

C függvények importálása Haskellbe

foreign import ccall "x.dll fooC" fooHS :: CInt -> IO CInt – ilyen szintaxissal lehet külső függvényeket importálni.

Fordítás GHC-vel

A fordításhoz szükség van egy Main nevű modulra. A -o kapcsolóval saját nevet adhatunk a lefordított fájlnak. IO monádok esetén fontos, hogy az utolsó utasítás print, return vagy más IO akció legyen.

Sikeres fordítás képe

Példakód

Haskell példakód kép formában
A példakód képként került beillesztésre az oktatási cél miatt.