haskell / c2hs

c2hs is a pre-processor for Haskell FFI bindings to C libraries
http://hackage.haskell.org/package/c2hs
Other
198 stars 50 forks source link

C2HS doesn't marshal bool #128

Closed ian-ross closed 9 years ago

ian-ross commented 9 years ago

The C bool type can't be marshalled directly through the Haskell FFI, so C2HS needs to generate some sort of intermediate wrapper layer to handle this case. For C functions with bool arguments, the C2HS-generated Haskell code will marshal from Haskell Bool to C int and the wrapper will then convert the argument from C int to C bool to call the function. For C functions with bool return values, the same sort of wrapping needs to work in the opposite direction.

trofi commented 9 years ago

Got caught by the same on ncurses bindings (C library is of version ncurses-5.9):

>>> Compiling source in /tmp/portage-tmpdir/portage/dev-haskell/ncurses-0.2.11/work/ncurses-0.2.11 ...
./setup build
Building ncurses-0.2.11...
Preprocessing library ncurses-0.2.11...

ERROR:
specs''=[CTypeSpec (CBoolType (NodeInfo ("/usr/include/ncursesw/curses.h": line 405) (("/usr/include/ncursesw/curses.h": line 405),5) (Name {nameId = 4351})))]
osize=Nothing
tspecs=[CBoolType (NodeInfo ("/usr/include/ncursesw/curses.h": line 405) (("/usr/include/ncursesw/curses.h": line 405),5) (Name {nameId = 4351}))]
lookup=Nothing

c2hs: Errors during expansion of binding hooks:

/usr/include/ncursesw/curses.h:405: (column 2) [ERROR]  >>> Illegal type!
  The type specifiers of this declaration do not form a legal ANSI C(89) type.
#if !NCURSES_OPAQUE
struct _win_st
{
...
        /* option values set by user */
/* line 405: */        bool    _notimeout;     /* no time out on function-key entry? */
ian-ross commented 9 years ago

@trofi I'm not quite sure why this has only started happening recently. I've sent a patch to the maintainer of ncurses to try to work around it for now, but I'm planning to make C2HS marshal C bool arguments properly this week...

ian-ross commented 9 years ago

I have a partial fix for this, but I don't think it will fix the ncurses problem, @trofi.

Marshalling of bool function arguments and return values, using C99's stdbool.h, works OK. C wrapper functions are generated in a .chs.c file to convert back and forth between C bool and C int (which is used to represent Haskell Bool values).

However, structures with bools in them are a bit of a problem. The size and alignment of _Bool values is not specified by the C99 standard and since there's no Haskell CBool type in the FFI, C2HS would somehow need to query the C compiler being used to work out the size of _Bool values (in order to calculate offsets and sizes for structures). I can certainly do this (by running a little C test program from within C2HS that determines the size and alignment requirements for _Bool values), but it's going to be pretty ugly. I need to think about it a little bit more.

ian-ross commented 9 years ago

I've now written some code to deal with bool values in C structures. I think that this should work on all platforms with relatively little pain, but I've had to do some slightly unpleasant things to determine the size of the C99 _Bool type for calculating structure member offsets. Specifically, C2HS now compiles and runs a small C test program to do this, using the C compiler from the results of running ghc --info. (This happens lazily, triggered by the need to calculate the size of _Bool, so it shouldn't disturb any existing code. I believe that it should work for most GHC setups, but I can't promise anything...)