2011-10-26 14 views
7

からHaskellのFFI機能PTRSを呼び出す:私が動作するように以下のコードを取得しようとしていますC

sample_hs :: CInt -> (CInt -> CInt) 
sample_hs x = (x+) 

foreign export ccall sample_hs :: CInt -> (CInt -> CInt) 

私はCで、このような何かをできるようにしたいと思います:

pf = sample_hs(2); 
result = pf(3); //Should be 5; 

私は、言語間のインターフェイスがどのように動作していないことを推測してい

error: too few arguments to function ‘sample_hs’

:私は、しかし、私はエラーメッセージを取得し、これを実行してみてください私はそれができると思った。私がやろうとしていることをする方法はありますか?

答えて

12

FFIでは、高次関数をエクスポートすることができます。あなたのHaskellのためにいくつかの変更は、しかし必要とされています

{-# LANGUAGE ForeignFunctionInterface #-} 
module Main where 

import Foreign.C.Types 
import Foreign 

foreign export ccall sample_hs :: CInt -> IO (FunPtr Sample) 

type Sample = CInt -> CInt 
foreign import ccall "wrapper" mkSample :: Sample -> IO (FunPtr Sample) 

sample_hs :: CInt -> IO (FunPtr Sample) 
sample_hs x = mkSample (x+) 

main = return() 

高階関数はHaskellで輸出されている明示的なFunPtrタイプを使用することによって。ちょっと分かりやすくするために、私は高次の型番をとしました。サンプルです。関数ポインタを作成するには、 "ラッパー"関数を使用する必要があります。したがって、余分なFFI宣言が必要です。

私はこれをテストしていませんが、うまくいくはずです。とにかくコンパイルされます。 FunPtrの詳細here

- EDIT私はそれをテストして正常に動作します。期待通りに5を返します。

Windowsでこれを実行している場合は、Haskell関数をエクスポートして自動的に.DLLにコンパイルするパッケージのhackage Hs2Libがあります。また、C/C++およびC#のインクルードを提供します。しかし、あなたがLinuxを使っているなら、私はまだそれに取り組んでいます。

恥知らずなプラグ:Hs2Libを使用してP

があなたのファイルに必要な唯一のものである:

module Test where 

-- @@ Export 
sample_hs :: Int -> IO (Int -> Int) 
sample_hs x = return (x+) 

とHs2lib

への単純な呼び出し
PS C:\Users\Phyx\Desktop> hs2lib .\Test.hs 
Linking main.exe ... 
Done. 

理由IOと明示的な戻り値は、型が右結合であるため、Int - >(Int - > Int)は単にInt - > Int - > Intであることです。しかし、Int - > IO(Int - > Int)は、関数を返すことを示します。関数ポインタの作成は副作用のため、IOになっています。 完全を期すために使用されるCファイルには、次のとおりです。

#include <stdio.h> 
#include <stdlib.h> 
#include "Hs2lib_FFI.h" 

/* 
* 
*/ 
int main(int argc, char** argv) { 

    HsStart(); 

    CBF1_t pf = sample_hs(2); 
    int result = pf(3); 
    printf("%d\n", result); 

    HsEnd(); 
    return (EXIT_SUCCESS); 
} 

だから、それはかなりプラグアンドプレイです。しかし、やはり今のところWindows用にしか動作しません。

+0

私が使っていた関数のシグネチャは、例よりずっと複雑で、あなたの例に従っていて、完璧に働いてくれました。ありがとう! –

4

私はFFIでそれを指定する句を見つけることができませんが、部分的なアプリケーション能力でエクスポートされた関数はありません。関数ポインタは、で表示されたことがないよう -

foreign export ccall sample_hs :: CInt -> CInt -> CInt 

に対応するCの宣言はまた、外国のタイプの構文は、高次関数をエクスポート禁止

int sample_hs(int, int); 

ない

type int (*function_pointer)(int); // or whatever the right syntax is 
function_pointer sample_hs(int); 

ありますC側の宣言。

関連する問題