Zoeken…


Syntaxis

  • buitenlandse import ccall onveilige "foo" hFoo :: Int32 -> IO Int32 {- Importeert een functie met de naam foo in een objectbestand en definieert het symbool hFoo dat kan worden opgeroepen met Haskell-code. -}

Opmerkingen

Hoewel cabal ondersteuning biedt voor het opnemen van een C- en C ++ -bibliotheken in een Haskell-pakket, zijn er enkele bugs. Ten eerste, als u gegevens (in plaats van een functie) gedefinieerd in zijn bo die wordt gebruikt in ao , en de lijst van de C-sources: ac, bc , dan kliek zal niet in staat om de gegevens te vinden zijn. Dit is gedocumenteerd in # 12152 . Een tijdelijke oplossing bij het gebruik van kliek is om het herschikken C-sources lijst te zijn C-sources: bc, ac . Dit werkt mogelijk niet bij het gebruik van stapel, omdat stapel de C-sources alfabetisch koppelt, ongeacht de volgorde waarin u ze vermeldt.

Een ander probleem is dat u C ++ -code in header (.h) -bestanden moet omringen met #ifdef __cplusplus bewakers. Dit komt omdat GHC de C ++ -code in header-bestanden niet begrijpt. U kunt nog steeds C ++ -code in header-bestanden schrijven, maar u moet deze omringen met bewakers.

ccall betrekking op de calling convention; momenteel worden ccall en stdcall (Pascal-conventie) ondersteund. Het unsafe trefwoord is optioneel; dit vermindert overhead voor eenvoudige functies, maar kan deadlocks veroorzaken als de buitenlandse functie voor onbepaalde tijd blokkeert of onvoldoende toestemming heeft om uit te voeren 1 .

C bellen vanuit Haskell

Om prestatieredenen, of vanwege het bestaan van volwassen C-bibliotheken, kunt u de C-code van een Haskell-programma gebruiken. Hier is een eenvoudig voorbeeld van hoe u gegevens kunt doorgeven aan een C-bibliotheek en een antwoord kunt krijgen.

foo.c:

#include <inttypes.h>

int32_t foo(int32_t a) {
  return a+1;
}

Foo.hs:

import Data.Int

main :: IO ()
main = print =<< hFoo 41

foreign import ccall unsafe "foo" hFoo :: Int32 -> IO Int32

Het unsafe trefwoord genereert een efficiëntere aanroep dan 'veilig', maar vereist dat de C-code nooit terugbelt naar het Haskell-systeem. Omdat foo volledig in C staat en nooit Haskell zal bellen, kunnen we unsafe .

We moeten ook cabal instrueren om te compileren en te koppelen in C-bron.

foo.cabal:

name:                foo
version:             0.0.0.1
build-type:          Simple
extra-source-files:  *.c
cabal-version:       >= 1.10

executable foo
  default-language: Haskell2010
  main-is:       Foo.hs
  C-sources:     foo.c
  build-depends: base

Dan kun je rennen:

> cabal configure
> cabal build foo
> ./dist/build/foo/foo
42

Het doorgeven van Haskell functioneert als callbacks naar C-code.

Het is heel gebruikelijk dat C-functies verwijzingen naar andere functies als argumenten accepteren. Het meest populaire voorbeeld is het instellen van een actie die moet worden uitgevoerd wanneer op een knop wordt geklikt in een GUI-toolkitbibliotheek. Het is mogelijk om Haskell-functies door te geven als C-callbacks.

Om deze C-functie te gebruiken:

void event_callback_add (Object *obj, Object_Event_Cb func, const void *data)

we importeren het eerst naar Haskell-code:

foreign import ccall "header.h event_callback_add"
    callbackAdd :: Ptr () -> FunPtr Callback -> Ptr () -> IO ()

Kijk nu hoe Object_Event_Cb is gedefinieerd in de C-header en definieer wat Callback is in Haskell:

type Callback = Ptr () -> Ptr () -> IO ()

Maak ten slotte een speciale functie die de Haskell-functie van het type Callback in een pointer zou veranderen FunPtr Callback :

foreign import ccall "wrapper"
    mkCallback :: Callback -> IO (FunPtr Callback)

Nu kunnen we callback met C-code registreren:

cbPtr <- mkCallback $ \objPtr dataPtr -> do
    -- callback code
    return ()
callbackAdd cpPtr

Het is belangrijk om toegewezen FunPtr gratis te FunPtr zodra u de terugbelaanmelding FunPtr :

freeHaskellFunPtr cbPtr


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow