我正试图通过内联C将以下结构类型编组为C和Haskell:
//defined in wayland-server-core.h
struct wl_listener {
struct wl_list link;
wl_notify_func_t notify;
};
//such that:
typedef void (*wl_notify_func_t)(struct wl_listener *listener, void *data);
根据inline-C的文档:
inline-c还可以处理用户定义的结构和枚举,只要它们是Storable的实例,并且您可以使用上下文将它们定义为inline-c。
在这里,我尝试精确地做到这一点:
-- In some module:
data C'WlListener -- Our (opaque) struct type in Haskell
initializeMyCtx = C.context $ C.baseCtx <> C.funCtx <> mempty {
C.ctxTypesTable = Data.Map.fromList [
-- ...
, (C.Struct "wl_listener", [t|C'WlListener|])
-- ...
]
}
-- In a different module:
initializeMyCtx
C.include "<wayland-server.h>"
C.include "<wayland-server-core.h>"
-- | We make C'WlListener an instance of Storable so we can conveniently
-- | pass it from C to Haskell and back via inline-C.
instance Storable C'WlListener where
sizeOf _ = fromIntegral $ [C.pure| int { sizeof(struct wl_listener) }|]
alignment _ = fromIntegral $ [C.pure| int { alignof(struct wl_listener) }|]
peek = error "peek not implemented for C'WlListener"
poke _ _ = error "poke not implemented for C'WlListener"
现在,当我尝试在Haskell中使用此功能
-- In a third module:
someIOFunc :: IO ()
someIOFunc = do
-- Initialize an empty struct (which intializes its members to 0 by default) to pass around from Haskell
myListener <- [C.exp| struct wl_listener { struct wl_listener listener }|]
-- ...
我收到以下错误:
• Unacceptable result type in foreign declaration:
‘C'WlListener’ cannot be marshalled in a foreign call
• When checking declaration:
foreign import ccall safe "inline_c_McWayFace_2" inline_c_ffi_6989586621679102285
:: IO C'WlListener
|
71 | myListener <- [C.exp| struct wl_listener { struct wl_listener listener }|]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^