[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
code.
> 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.
Duncan
More information about the C2hs
mailing list