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用にしか動作しません。
私が使っていた関数のシグネチャは、例よりずっと複雑で、あなたの例に従っていて、完璧に働いてくれました。ありがとう! –