11

我正在尝试在我的 C 代码中使用 Haskell 库。我尝试使用的 Haskell 函数的类型String -> IO [Reference]Reference一个相当复杂的结构(有关详细信息,请参见此处)。

根据阅读各种文档,我似乎必须将这种类型作为一个实例,Storable并且在我的 c 代码中定义一个类似的结构才能访问它。对于如此复杂的类型,这似乎是很多非常重复的工作。有没有办法自动化这个?怎么会去做这样的事情?

4

2 回答 2

8

It depends on you actual use case, but... It could be easier to export Reference as opaque type (via Foreign.StablePtr), and export getter functions to access individual fields.

Please let me know if you need more details, and I'll expand the answer.

于 2013-01-26T16:30:22.133 回答
4

我写了一个小工具(使用 Template Haskell),它自动将任何由原始类型(Int、Float、Double、Char、Bool)、可编组类型的列表和由可编组类型组成的结构组成的数据类型编组为相应的C型。

  • 原始类型成为它们的 C 对应物:Int -> int,Float -> float。布尔变成整数。
  • “结构”(数据 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。)它由两个文件组成,您只需将它们复制到您的代码中。用法:

$(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 回答