5

我正在使用一个 C 代码库

typedef void(* wl_notify_func_t) (struct wl_listener *listener, void *data) 

//...

struct wl_listener {
  struct wl_list link;
  wl_notify_func_t notify; //<-- I'd like to return this
};

并使用了 Haskell 代码

type NotifyFuncT = FunPtr (Ptr C'WlListener -> Ptr () -> IO ())

initializeMyCtx = C.context $ C.baseCtx <> C.funCtx <> mempty {
  C.ctxTypesTable = Data.Map.fromList [
     (C.Struct "wl_listener", [t|C'WlListener|])
  -- ...
  ,  (C.TypeName "wl_notify_func_t", [t|NotifyFuncT|])
  ]
}

someHaskellFunction :: Ptr C'WlListener -> IO NotifyFuncT
someHaskellFunction ptrToWlListener = do
  funPtr <- [C.block| wl_notify_func_t {return $(struct wl_listener * ptrToWlListener)->notify;}|]
  return funPtr

不幸的是,我从 inline-C 代码块中得到一个错误,它基本上说:

unexpected identifier  wl_notify_func_t

那么我正在做的事情甚至可能使用 inline-C 吗?

4

2 回答 2

6

您错误地使用了上下文。

C.context :: Context -> Q [Dec]

它被称为模板 Haskell 顶级拼接。你所做的就是定义

intializeMyCtx :: Q [Dec]

这是一个Q-action如果执行初始化你的上下文,但不是. 所以,解决这个问题:

type NotifyFuncT = FunPtr (Ptr C'WlListener -> Ptr () -> IO ())

C.context $ C.baseCtx <> C.funCtx <> mempty {
  C.ctxTypesTable = Data.Map.fromList [
     (C.Struct "wl_listener", [t|C'WlListener|])
  -- ...
  ,  (C.TypeName "wl_notify_func_t", [t|NotifyFuncT|])
  ]
}

其次,someHaskellFunction有点过于复杂了。如果你有一个更复杂的功能,那么C.block可能是有保证的,但现在一个单一的C.exp就可以完成所有事情。

someHaskellFunction :: Ptr C'WlListener -> IO NotifyFuncT
someHaskellFunction ptr = [C.exp| wl_notify_func_t { $(struct wl_listener *ptr)->notify } |]
于 2019-01-22T23:57:07.923 回答
0

我问题中的代码有效。我只是忘了包含一个 C 上下文。

于 2019-01-22T23:37:39.270 回答