11

CコードでHaskellライブラリを使用しようとしています。私が使おうとしているHaskell関数は、かなり複雑な構造のタイプです(詳細はString -> IO [Reference]こちらをご覧ください)。Reference

さまざまなドキュメントを読んだことに基づいて、このタイプをのインスタンスにStorableし、それにアクセスできるようにするためにcコードで同様の構造体を定義する必要があるようです。これは、このような複雑なタイプでは非常に反復的な作業のようです。これを自動化する方法はありますか?どうやってそんなことをするのでしょうか?

4

2 に答える 2

8

実際のユースケースによって異なりますがReference、不透明(OPAQUE)型として(Foreign.StablePtrを介して)エクスポートし、ゲッター関数をエクスポートして個々のフィールドにアクセスする方が簡単な場合があります。

詳細が必要な場合はお知らせください。回答を拡大します。

于 2013-01-26T16:30:22.133 に答える
4

私は(テンプレートHaskellを使用して)小さなツールを作成しました。これは、プリミティブ型(Int、Float、Double、Char、Bool)、マーシャラブルタイプのリスト、およびマーシャラブルタイプで構成される構造体で構成されるデータ型を対応するデータ型に自動的にマーシャリングします。 Cタイプ。

  • プリミティブ型はCの対応物になります:Int-> int、Float->float。Boolはintになります。
  • 「構造体」(データS = S ...)は、Haskellの「構造体」のマーシャリングされたメンバーを持つ構造体へのポインターになります。
  • 配列([S])は、その型へのポインターの配列へのポインターと、そこにある要素の数を示すintで構成される構造体へのポインターになります。

したがって、この:

data Test = Test [MyStruct] Int
data MyStruct = MyStruct Int

Cでは次のようになります。

struct MyStruct {
  int x;
}

struct ArrayStruct {
  MyStruct** array;
  int count;
}

struct Test {
  ArrayStruct* arr_str;
  int y;
}

ツールは次のとおりです: https ://github.com/food2games/fieldmarshal

(C#部分もありますが、HsFieldMarshalが必要です。)これは2つのファイルで構成されており、コードにコピーするだけです。使用法:

$(makeStorable ''YourType)

サブタイプに対して自動的に保存可能なコードを実行しないことに注意してください。したがって、これがある場合:

data Type1 = Type1 Int Float
data Type2 = Type2 Int Type1

各データ型に保存可能なインスタンスを生成する必要があるよりも:

$(makeStorable ''Type1)
$(makeStorable ''Type2)

また、Storableインスタンスの生成よりも前にデータ型を宣言する必要があることに注意してください(これはTHが原因です)。したがって、これは機能しません。

$(makeStorable ''Wrong)
data Wrong = Wrong Int

これは絶対に絶対確実というわけではなく、単純なアプリには十分ですが、より複雑なコードで作業している場合は、物事がかなり簡単に台無しになる可能性があります。

于 2013-01-31T08:27:12.080 に答える