サーチ…


構文

  • foreign import ccall unsafe "foo" hFoo :: Int32 - > IO Int32 { - いくつかのオブジェクトファイルでfooという名前の関数をインポートし、Haskellコードで呼び出すことができるシンボルhFooを定義します。 - }

備考

cabalはCおよびC ++ライブラリをHaskellパッケージに含めることをサポートしていますが、いくつかのバグがあります。まず、 aoで使用されるboで定義されたデータ(関数ではない)があり、 C-sources: ac, bcをリストすると、cabalはデータを見つけることができません。これは#12152に記載されています。カバールを使用する場合の回避策は、 C-sourcesリストをC-sources: bc, ac C-sourcesに並べ替えることC-sources: bc, ac 。スタックを使用すると、 C-sourcesアルファベット順にリンクするので、スタックの使用順序に関係なく、スタックを使用すると機能しないことがあります。

別の問題は、ヘッダー(.h)ファイルのC ++コードを#ifdef __cplusplusガードで囲む必要があることです。これは、GHCがヘッダファイルのC ++コードを理解していないためです。ヘッダーファイルにC ++コードを書き込むことはできますが、ガードに囲む必要があります。

ccall呼び出し規約を指します。現在、 ccallstdcall (Pascal convention)がサポートされています。 unsafeキーワードはオプションです。これは、単純な機能のためのオーバーヘッドが減少しますが、外国の機能ブロックが無期限に、または実行するための十分な権限がある場合は、デッドロックを引き起こす可能性が1を

ハスケルからCを呼び出す

パフォーマンス上の理由から、または成熟したCライブラリの存在により、HaskellプログラムからCコードを呼び出すことができます。ここでは、データをCライブラリに渡して答えを返す簡単な例を示します。

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

unsafeキーワードは、「safe」よりも効率的な呼び出しを生成しますが、CコードがHaskellシステムへのコールバックを決して必要としません。 fooは完全にC言語であり、決してHaskellを呼び出さないので、 unsafeを使うことができます。

私たちはC言語でコンパイルしリンクするようカバールに指示する必要もあります。

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

次に、実行することができます:

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

HaskellをCコードへのコールバックとして渡します。

C関数が他の関数へのポインタを引数として受け入れることは非常に一般的です。最も一般的な例は、GUIツールキットライブラリでボタンがクリックされたときに実行されるアクションを設定することです。 Haskell関数をCコールバックとして渡すことは可能です。

このC関数を呼び出すには:

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

最初にそれをHaskellのコードにインポートします:

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

次に、CヘッダーでObject_Event_Cbがどのように定義されているかを見て、HaskellのCallback定義します。

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

最後に、 Callback型のHaskell関数をポインタFunPtr Callback Callbackにラップする特別な関数を作成します。

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

コールバックをCコードで登録することができます:

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

コールバックの登録を解除すると、割り当てられたFunPtrを解放することが重要です。

freeHaskellFunPtr cbPtr


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow