Extension to the FFI to allow macro expansions to be avoided

Alastair Reid alastair at reid-consulting-uk.ltd.uk
Thu Apr 8 05:18:24 EDT 2004

Ian Lynagh writes:
> Some C libraries (curses is the one I have to hand) provide macros in
> addition to functions in some cases for efficiency reasons. If you use
> the FFI to import such a function thus:

I was a bit confused by what Ian meant by this so, in case it helps others, 
here's an extract from curses.h.

extern NCURSES_EXPORT(int) wstandend (WINDOW *);	/* generated */
#define wstandend(win) (wattrset(win,A_NORMAL))

There seem to be a substantial number of these:

  $ grep generated /usr/include/curses.h | wc -l

As far as I can see, there is no conditional compilation to let you turn the 
macros off so you would have to write 117 individual #undefs, 117 stub 
functions or whatever.

Now that I understand the problem, my feeling is that the problem is not with 
curses but with GHC's compilation method.  GHC is using a shortcut by 
pretending that the ffi is for interfacing to cpp+C whereas the ffi is quite 
clear that it is for interfacing to C.  So, I think the thing to do is fix 
GHC.  For that reason I vote for:

> Surrounding the function with parentheses so the macro doesn't match.
> The offending line above would be
> _ccall_result = ((wstandend)((_ccall_arg1)));

where the decision to insert parens is decided by a command-line flag.  
(Ideally, this flag would affect foreign imports in that file but not any 
obtained from imported modules.)

I like this approach because it means that we don't have to strip the parens 
off when using the other compilation techniques such as GHC's NCG or Hugs 
generating stub functions for everything.

Alternatively add an appropriate set of #undefs for this particular file.  The 
following comes close to doing the job.

grep generated /usr/include/curses.h
  | perl -pe 's/^.*\)\s+(\w+).*/#undef \1/'

Stick the result in a header file like this:


    #include "curses.h"
    #ifdef __GHC__
    #undef macro1
    #undef macro117

and use curses_wrapper.h instead of curses.h in the Haskell code.

Alastair Reid

More information about the FFI mailing list