Может ли in-C на Haskell вернуть typedef к указателю на функцию?
Я работаю с базой кода 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?
2 ответа
Вы используете контексты неправильно.
C.context :: Context -> Q [Dec]
Он должен называться шаблоном верхнего уровня Template Haskell. Все, что вы сделали, это определить
intializeMyCtx :: Q [Dec]
Который является Q
- действие, которое инициализирует ваш контекст, если выполнено, но не выполнено. Итак, исправьте это:
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 } |]
Код в моем вопросе работает. Я просто забыл включить контекст Си.