2017-12-04 20 views
2

外部ファンクションコールからスタックに3つのInt#を返す方法はありますか?ここではCコード(または私は実際に興味があるものにオブジェクトファイルと同等を生成Cコード)は、次のとおりです。FFI:スタック上に3つのInt#を返す

struct Tuple { 
    int bezout1, bezout2, gcd; 
} 

struct Tuple extendedGcd(int a, int b) { 
    /* elided */ 
} 

(# Int#, Int#, Int# #)ccallでサポートされていないので、これはコンパイルされません。

:ワンセグ障害( MagicHashGHCForeignImportPrimForeignFunctionInterfaceUnboxedTuples、および MagicHashとはいえ、コンパイルした)次の
foreign import ccall "extendedGcd" 
    extendedGcd :: Int# -> Int# -> (# Int#, Int#, Int# #) 

すべての私の用途私はこれがあると想像

:0

私はこの種の問題を回避するためにいくつかの努力があったこといくつかの証拠を見つけることができます一般的な問題ですが、実際の例は見つかりません。これはすべて可能ですか?

+0

インポートするC関数の種類は何ですか? Cの型は、Haskellでどの型に割り当てることができるのかを完全に決めると思います。 'ccall'はCの呼び出し規約をモデル化することを意図しています。 C自体に複数のリターンという概念はないので、 'ccall'にも存在しません。自動構造化マーシャリングの提案は、 'c2hs'などを使用して、マーシャル構造体のコードを自動的に生成することに賛成して批判されたと思います。 – user2407038

+0

@ user2407038確かにそれはCタイプ(私はいくつかのコードを含んでいます)を持っていますが、 'Storable'インスタンス' c2hs'はポインタを渡しているとみなします。ここでは、ボックス化されていない製品(スタックに3つの生のintを渡します)を渡したいと思います。私の理解は、ハスケルでそれを行う唯一の方法は、ボックス化されていないタプルを経由することです。 – Alec

+0

確かに、一時的なメモリをどこかに割り当てることなく、C関数から構造体を返す簡単な方法はありません。これがパフォーマンス上のペナルティ(またはそうする上での他の障害)が大きすぎる場合、唯一の方法は 'prim'を使用して、あなたが行ったようにボックス化されていないタプルを返すことです。しかし、あなたの関数が普通のC関数であれば、 'prim'関数が使用する必要があるGHC呼び出し規約に従いません。あなたはあなたの関数の周りにC - ラッパーを書く必要があります。 – user2407038

答えて

1

Cではなくアセンブリでプロシージャを直接実装することができれば、これを行うのはかなり簡単です。これは非常に簡単です。参照:http://brandon.si/code/almost-inline-asm-in-haskell-with-foreign-import-prim/。多分GCDアルゴリズムのためにこれはあなたのために大丈夫でしょう。

hereをまとめた完全なカバールプロジェクトがあります。

+2

これは実際にGCDのためのものではありません。これは、Rustタプルを使ったHaskell interopを生成するためのものです:)それでもやはり役に立ちます!ありがとうございます。 – Alec

関連する問題