Suche…


Syntax

  • fremder import ccall unsicher "foo" hFoo :: Int32 -> IO Int32 {- Importiert eine Funktion namens foo in eine Objektdatei und definiert das Symbol hFoo das mit Haskell-Code aufgerufen werden kann. -}

Bemerkungen

Cabal unterstützt zwar das Einbinden von C- und C ++ - Bibliotheken in ein Haskell-Paket, es gibt jedoch einige Fehler. Erstens, wenn Sie in bo definierte Daten (und nicht eine Funktion) haben, die in ao , und die C-sources: ac, bc , dann kann cabal die Daten nicht finden. Dies ist in # 12152 dokumentiert. Eine Problemumgehung bei Verwendung von Kabal besteht darin, die Liste der C-sources in C-sources: bc, ac . Dies funktioniert möglicherweise nicht, wenn Stack verwendet wird, da Stack die C-sources alphabetisch verknüpft, unabhängig von der Reihenfolge, in der Sie sie auflisten.

Ein #ifdef __cplusplus ist, dass Sie jeden C ++ - Code in Header-Dateien (.h) mit #ifdef __cplusplus Guards umgeben müssen. Dies liegt daran, dass GHC C ++ - Code in Header-Dateien nicht versteht. Sie können weiterhin C ++ - Code in Header-Dateien schreiben, aber Sie müssen ihn mit Wachen umgeben.

ccall bezieht sich auf die aufrufende Konvention ; derzeit werden ccall und stdcall (Pascal-Konvention) unterstützt. Das unsafe Schlüsselwort ist optional. dies reduziert für einfache Funktionen Overhead , sondern kann Deadlocks verursachen , wenn die Fremdfunktionsblöcke auf unbestimmte Zeit oder unzureichende Berechtigung hat , auszuführen 1 .

C aus Haskell anrufen

Aus Leistungsgründen oder wegen des Vorhandenseins ausgereifter C-Bibliotheken möchten Sie möglicherweise C-Code aus einem Haskell-Programm aufrufen. Hier ein einfaches Beispiel, wie Sie Daten an eine C-Bibliothek übergeben und eine Antwort erhalten können.

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

Das unsafe Schlüsselwort erzeugt einen effizienteren Aufruf als 'safe', setzt jedoch voraus, dass der C-Code niemals einen Rückruf an das Haskell-System ausführt. Da foo vollständig in C ist und Haskell niemals anrufen wird, können wir unsafe .

Wir müssen Kabal außerdem anweisen, in C-Quelle zu kompilieren und zu verknüpfen.

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

Dann kannst du laufen:

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

Übergeben von Haskell-Funktionen als Rückrufe an C-Code.

Es ist üblich, dass C-Funktionen Zeiger auf andere Funktionen als Argumente akzeptieren. Das bekannteste Beispiel ist das Festlegen einer Aktion, die ausgeführt wird, wenn eine Schaltfläche in einer GUI-Toolkit-Bibliothek angeklickt wird. Haskell-Funktionen können als C-Callbacks übergeben werden.

So rufen Sie diese C-Funktion auf:

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

Wir importieren es zuerst in den Haskell-Code:

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

Object_Event_Cb nun betrachten, wie Object_Event_Cb im C-Header definiert ist, definieren Sie, was Callback in Haskell ist:

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

Erstellen Sie schließlich eine spezielle Funktion, die die Haskell-Funktion vom Typ Callback in einen Zeiger FunPtr Callback :

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

Jetzt können wir einen Rückruf mit C-Code registrieren:

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

Es ist wichtig, FunPtr Sie den zugewiesenen FunPtr sobald Sie den Rückruf FunPtr :

freeHaskellFunPtr cbPtr


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow