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
117
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:
curses_wrapper.h:
#include "curses.h"
#ifdef __GHC__
#undef macro1
...
#undef macro117
#endif
and use curses_wrapper.h instead of curses.h in the Haskell code.
--
Alastair Reid
More information about the FFI
mailing list