1

'C'のwiringPiライブラリには、次のタイプの関数があります。

extern void (*pinMode) (int pin, int mode) ;

FunPtrでFFIを使用してhaskellから呼び出してみました。だから私はしました、

foreign import ccall unsafe "wiringPi.h &pinMode" c_pinMode 
        :: FunPtr (CInt -> CInt -> IO ())
foreign import ccall "dynamic" dc_pinMode 
        :: FunPtr (CInt -> CInt -> IO ()) -> (CInt -> CInt -> IO ())

しかし、何らかの理由で、コンパイルしても、「pinMode」が指す関数を呼び出していないようです。

そこで、通常のForeign.Ptrを使用してみました。これは、Ptrを覗いて、「pinMode」が指す基になる「C」関数への参照を取得できる可能性があると考えたためです。だから私は試しました、

foreign import ccall "wiringPi.h &pinMode" c_pinMode
    :: Ptr (Ptr (CInt -> CInt -> IO ()))

次に、「pinMode」を呼び出すhaskell関数の実装で、peekを2回使用して、基になる関数への参照を取得しました。(CInt -> CInt -> IO ())しかし、コンパイラが型の関数が「保存可能な」型クラスのインスタンスではないと私に言う場合、コンパイルエラーが発生し続けます。

そこで、保存可能な型クラスをチェックして、保存可能な型クラス(CInt -> CInt -> IO ())のインスタンスを作成しました。必要な最小限の実装は、ピーク、ポーク、およびその他のいくつかの関数です。ポインタによる参照です。

根本的な何かが欠けているような気がします。誰かが私を正しい方向に向けてくれませんか?

よろしくお願いします

4

1 に答える 1

2

foo.cで定義されたC関数ポインターがあるとします。

void foo(int x, int y)
{
    printf("foo: sum = %d\n", x+y);
}

typedef void (*FooPtr) (int, int);
FooPtr fooptr = foo;

を指す関数を呼び出すにはfooptr、静的アドレスのインポートだけでなく、動的インポートも宣言する必要があります。FunPtr動的スタブは、値を対応するHaskell関数に変換するのに役立ちます。

type Foo = CInt -> CInt -> IO ()

foreign import ccall "foo.c &fooptr" fooptr :: Ptr (FunPtr Foo)
foreign import ccall "dynamic" mkFooFun :: FunPtr Foo -> Foo

main = do
    funcptr <- peek fooptr
    mkFooFun funcptr 1 2

fooptr外部関数を指すインポートされたアドレスです。そのタイプはどちらPtr (Ptr a)でもありませんFunPtr a

fooのアドレスをインポートすると、そのタイプはになりますFunPtr Foo。それを使用するには、まだからの助けが必要mkFooFunです。

foreign import ccall "foo.c &foo" fooptr2 :: FunPtr Foo
main = mkFooFun fooptr2 1 2

この例では、にアクセスできるためfoo、最も簡単な呼び出し方法は次のとおりfooです。

foreign import ccall "foo.c foo" foo :: Foo
main = foo 1 2
于 2013-03-05T08:30:35.820 に答える