我正在尝试在我的 C 代码中使用 Haskell 库。我尝试使用的 Haskell 函数的类型String -> IO [Reference]
是Reference
一个相当复杂的结构(有关详细信息,请参见此处)。
根据阅读各种文档,我似乎必须将这种类型作为一个实例,Storable
并且在我的 c 代码中定义一个类似的结构才能访问它。对于如此复杂的类型,这似乎是很多非常重复的工作。有没有办法自动化这个?怎么会去做这样的事情?
我正在尝试在我的 C 代码中使用 Haskell 库。我尝试使用的 Haskell 函数的类型String -> IO [Reference]
是Reference
一个相当复杂的结构(有关详细信息,请参见此处)。
根据阅读各种文档,我似乎必须将这种类型作为一个实例,Storable
并且在我的 c 代码中定义一个类似的结构才能访问它。对于如此复杂的类型,这似乎是很多非常重复的工作。有没有办法自动化这个?怎么会去做这样的事情?
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.
我写了一个小工具(使用 Template Haskell),它自动将任何由原始类型(Int、Float、Double、Char、Bool)、可编组类型的列表和由可编组类型组成的结构组成的数据类型编组为相应的C型。
所以这:
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
这绝对不是万无一失的,对于简单的应用程序来说已经足够了,但是如果您正在使用更复杂的代码,事情很容易变得一团糟。