Вычисление структуры из C в Haskell с использованием Inline-C - PullRequest
0 голосов
/ 26 января 2019

Я пытаюсь упорядочить следующий тип структуры между C и Haskell через inline-C:

//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 canтакже обрабатывают определяемые пользователем структуры и перечисления, при условии, что они являются экземплярами 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 }|]
   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...