Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can Haskell's inline-C return a typedef to a function pointer?

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?

like image 348
George Avatar asked Jan 22 '19 20:01

George


People also ask

What is typedef in function pointer?

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.

How can I declare a function that can return a pointer to a function of the same type?

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.

What is typedef void?

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.

How do you declare a function pointer in C++?

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).


1 Answers

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 } |]
like image 132
HTNW Avatar answered Oct 02 '22 23:10

HTNW