[C2hs] Function Hooks and Calling Convention

Duncan Coutts duncan.coutts at worc.ox.ac.uk
Tue Sep 22 08:44:09 EDT 2009

On Mon, 2009-09-21 at 17:45 -0700, Thomas DuBuisson wrote:
> Playing with function hooks, I've found two issues that draw my ire.
> FYI, this is more of a partial experience report than a question.

Great, thanks.

> For an example, let us discuss the kernel function
> "pci_register_driver", which is actually a macro and thus not handled
> by the function hooks.  The first step in fixing this is a CPP
> section:
>     #c
>     inline int pci_register_driver2(pci_dev_t d)
>     {
>         pci_register_driver(d);
>     }
>     #endc
> So I'd call this experience number 1 - it is entirely possible to
> automatically generate wrapper functions for macros ( {#macro ...}? or
> even {#fun ...} handling macros too).

Right. I'm not sure you can make it inline however, at least not in any
meaningful way.

> Perhaps there's not enough interest for anyone to make this change but
> I expect this to come up more and more often.

Yes it happens quite a bit.

> I'll note that this is very similar to the issue of importing pure
> macros (macros that don't wrap a function call), which would be a nice
> feature.

Right, since the wrapper C function would end up containing the code of
the macro, so it doesn't matter if it's a function call or some other

> I can now write the hook and c2hs will parse things ok:
>     {#fun pci_register_driver2 as ^
>         {id  `PCIDriver'
>         } -> `Int' id#}
> generating a foreign import:
>     foreign import ccall safe "pci.chs.h pci_register_driver2"
>       pciRegisterDriver'_ :: ((PCIDriver) -> (IO CInt))
> And all seems well... except that I'm aiming to use this in
> interfacing with the Linux kernel.  The generated *.chs.h file
> will/must be compiled into an object file using the Linux build
> system, which defaults to a regparm3 calling convention.

So the other problem is that it only makes a .h file, not a .c file.
Really you want to be able to inject things into the header that c2hs
reads, and separately into a .c file. In a Cabal build you'd then want
Cabal to compile the .c file and include it into the result. For your
project you obviously have to handle the .c file yourself.

> Why does c2hs automatically assume its a ccall?  I could really use an
> opportunity to insert an alternate convention.

Right, it only knows about ccall. It would be possible to extend c2hs to
understand the C attributes which declare that the function is regparam.
Though actually that might not help for the kernel headers because I
think they do not declare the regparam calling convention and just rely
on gcc flags when compiling.

> In the end the solution I have is to manually write the above C
> section and the foreign import call using a regparm3 calling
> convention.  This isn't to say c2hs isn't used - its still hugely
> helpful (so long as the headers remain easy to convert to ANSI C), but
> just my quick experience.

BTW, what do you mean about ANSI C? Language.C and by extension c2hs
should be able to handle all the GNU C constructs. That's not to say
c2hs takes them into account of course, but it shouldn't fall over.

So yes, I think all these issues are solvable. As usual the difficulty
is finding enough people with enough time to actually do the work. I
think c2hs could become the standard Haskell ffi binding tool, taking
over from hsc2hs, but it needs a bit of love.


More information about the C2hs mailing list