我正在尝试编写一个与 C 通信的 Haskell 程序(最终通过 GHC-iOS 用于 iOS)。我希望它将一个字符串从 C 传递到 Haskell,让 Haskell 处理它,然后通过 hsc2s 将一些数据类型从 Haskell 返回到 C 结构。我一直未能找到一个清晰、简单的教程。 Haskell 从 C 中唯一需要的是字符串,没有别的。
我对第一部分没有任何问题,将字符串传递给 Haskell。
testPrint :: CString -> IO ()
testPrint c = do
s <- peekCString c
putStrLn s
出于测试目的和将来的参考,我只想能够处理类似以下的事情。
C Struct
struct testdata {
char *a;
char *b;
int c;
};
Haskell 数据类型
data TestData = TestData {
a :: String,
b :: String,
c :: Int
} deriving Show
-- not sure what the type would look like
testParse :: CString -> TestData
我知道我需要将 TestData 类型分类为 Storable 并实现 peek、poke、sizeOf 和对齐,但我需要先看一个简单的示例,然后才能真正理解它。大多数教程都需要外部库,这使得它比需要的更加复杂。
以下是我看过的资源:
Stackoverflow - 如何使用 hsc2hs 绑定到常量、函数和数据结构? https://stackoverflow.com/questions/6056323/how-to-use-hsc2hs-to-bind-to-constants-functions-and-data-structures
Haskell Cafe - 适合初学者的 FFI https://groups.google.com/forum/#!topic/haskell-cafe/mJalEcZ-dTI
将 Haskell 接口写入 C 代码:hsc2hs https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/hsc2hs.html
Haskell 维基百科 - FFI https://en.wikibooks.org/wiki/Haskell/FFI
编辑:目前我陷入困境(在 C 中调用 setFoo 时出现分段错误)
Haskell 代码片段
instance Storable Foo where
sizeOf = #{size foo}
alignment = alignment (undefined :: CString)
poke p foo = do
#{poke foo, a} p $ a foo
#{poke foo, b} p $ b foo
#{poke foo, c} p $ c foo
peek p = return Foo
`ap` (#{peek foo, a} p)
`ap` (#{peek foo, b} p)
`ap` (#{peek foo, c} p)
foreign export ccall "setFoo" setFoo :: Ptr Foo -> IO ()
setFoo :: Ptr Foo -> IO ()
setFoo f = do
newA <- newCString "abc"
newB <- newCString "def"
poke f (Foo newA newB 123)
C 代码片段
foo *f;
f = malloc(sizeof(foo));
foo->a = "bbb"
foo->b = "aaa"
foo->c = 1
// this is incorrect
// setFoo(&f);
// this is correct
setFoo(f);