在 c2hs 中将裸结构从 C 返回到 Haskell
Returning a bare struct from C to Haskell in c2hs
我正在尝试绑定到 returns 结构(按值)的 C 函数。我知道我可以使用 FFI 手动包装它,但无法弄清楚如何哄骗 c2hs 生成正确的代码。似乎认为我的函数正在返回一个指针。
这是一个简单的例子:
module Point where
#c
struct point {
int x;
int y;
};
struct point get_zero(void);
#endc
data Point = Point { x :: Int, y :: Int }
instance Storable Point where
sizeOf _ = {#sizeof point#}
alignment _ = {#alignof point#}
peek p = point <$> liftA fromIntegral ({#get point.x #} p)
<*> liftA fromIntegral ({#get point.y #} p)
poke p s = do {#set point.x #} p (fromIntegral $ x s)
{#set point.y #} p (fromIntegral $ y s)
{#pointer *point as PointPtr -> Point#}
-- Causes error:
{#fun get_zero as ^ { } -> `Point'#}
错误:
c2hs: Errors during expansion of binding hooks:
Point.chs:25: (column 28) [ERROR] >>> Missing "out" marshaller!
There is no default marshaller for this combination of Haskell and C type:
Haskell type: Point
C type : (Ptr ())
目前不可以。您可以制作一个 returns 指针结果的包装器:
void get_zero_wrapper(struct point* p) {
*p = get_zero();
}
请注意,您必须为结构分配 space,例如使用 alloca
.
有一个 proposal 支持在 FFI 中按值传递和返回 C 结构。但它不太可能在不久的将来实施,因为它没有得到社区的足够重视。该提案需要更仔细的设计,例如目前尚不清楚它将如何与其他语言功能一起使用。
我正在尝试绑定到 returns 结构(按值)的 C 函数。我知道我可以使用 FFI 手动包装它,但无法弄清楚如何哄骗 c2hs 生成正确的代码。似乎认为我的函数正在返回一个指针。
这是一个简单的例子:
module Point where
#c
struct point {
int x;
int y;
};
struct point get_zero(void);
#endc
data Point = Point { x :: Int, y :: Int }
instance Storable Point where
sizeOf _ = {#sizeof point#}
alignment _ = {#alignof point#}
peek p = point <$> liftA fromIntegral ({#get point.x #} p)
<*> liftA fromIntegral ({#get point.y #} p)
poke p s = do {#set point.x #} p (fromIntegral $ x s)
{#set point.y #} p (fromIntegral $ y s)
{#pointer *point as PointPtr -> Point#}
-- Causes error:
{#fun get_zero as ^ { } -> `Point'#}
错误:
c2hs: Errors during expansion of binding hooks:
Point.chs:25: (column 28) [ERROR] >>> Missing "out" marshaller!
There is no default marshaller for this combination of Haskell and C type:
Haskell type: Point
C type : (Ptr ())
目前不可以。您可以制作一个 returns 指针结果的包装器:
void get_zero_wrapper(struct point* p) {
*p = get_zero();
}
请注意,您必须为结构分配 space,例如使用 alloca
.
有一个 proposal 支持在 FFI 中按值传递和返回 C 结构。但它不太可能在不久的将来实施,因为它没有得到社区的足够重视。该提案需要更仔细的设计,例如目前尚不清楚它将如何与其他语言功能一起使用。