我正在尝试在我的C代码中使用Haskell库。我尝试使用的Haskell函数的类型为String -> IO [Reference]
,其中Reference
是一个相当复杂的结构(参见here for details)。
基于阅读各种文档,似乎我必须使这种类型成为Storable
的实例,并且在我的c代码中定义了类似的结构才能访问它。对于如此复杂的类型,这似乎是很多非常重复的工作。有没有办法实现自动化?怎么会做这样的事情?
答案 0 :(得分:8)
这取决于你的实际用例,但是......
可以更轻松地将Reference
导出为opaque类型(通过Foreign.StablePtr),并导出getter函数以访问各个字段。
如果您需要更多详细信息,请告诉我,我会扩大答案。
答案 1 :(得分:4)
我写了一个小工具(使用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)
另请注意,您必须在可存储实例生成之前声明数据类型(这是因为TH)。所以这不起作用:
$(makeStorable ''Wrong)
data Wrong = Wrong Int
这绝对不是万无一失的,对于简单的应用程序来说已经足够了,但是如果你正在使用更复杂的代码,那么事情就会很容易搞砸。