I'm working with a C code base for which
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
};
and have used the Haskell code
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
Unfortunately, I get an error from the inline-C code block which essentially says:
unexpected identifier wl_notify_func_t
So is what I'm doing even possible with inline-C?
A typedef, or a function-type alias, helps to define pointers to executable code within memory. Simply put, a typedef can be used as a pointer that references a function.
You cannot return a function in C - you return a pointer to a function. If you mean to define a function which returns a pointer to a function which again returns a pointer to a function and so on, then you can use typedef to implement it.
typedef void (*MCB)(void); This is one of the areas where there is a significant difference between C, which does not - yet - require all functions to be prototyped before being defined or used, and C++, which does.
We declare the function pointer, i.e., void (*ptr)(char*). The statement ptr=printname means that we are assigning the address of printname() function to ptr. Now, we can call the printname() function by using the statement ptr(s).
You are using contexts incorrectly.
C.context :: Context -> Q [Dec]
It is meant to be called as a Template Haskell top-level splice. All you've done is define
intializeMyCtx :: Q [Dec]
Which is a Q
-action that would initialize your context if executed, but isn't. So, fix that:
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|])
]
}
Second, someHaskellFunction
is a tad overcomplicated. If you have a more complicated function, then C.block
may be warranted, but right now a single C.exp
will do everything.
someHaskellFunction :: Ptr C'WlListener -> IO NotifyFuncT
someHaskellFunction ptr = [C.exp| wl_notify_func_t { $(struct wl_listener *ptr)->notify } |]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With