[This has come from the cvs-ghc list. All the info should be in this mail, though].
The problem =========== 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: ----- module Q where import Foreign.Ptr (Ptr) import Foreign.C.Types (CInt) foreign import ccall unsafe "static curses.h wstandend" wstandend :: Ptr a -> IO CInt ----- Then GHC fails if not using the NCG (which AFAIK is available on only handful of platforms; the generated code efficiency may also be an issue if you don't have enough foreign imports to warrant splitting them off into their own module): $ ghc -fffi -c Q.hs -O /tmp/ghc1164.hc: In function `Q_zdwccall_entry': /tmp/ghc1164.hc:29: warning: dereferencing `void *' pointer /tmp/ghc1164.hc:29: error: request for member `_attrs' in something not a structure or union $ as it is creating code like this (line 29 is the one containing "wstandend"): { I_ _ccall_result; StgAddr _ccall_arg1=_B0_; CALLER_SAVE_SYSTEM _ccall_result = (wstandend((_ccall_arg1))); CALLER_RESTORE_SYSTEM _B3_=_ccall_result; } which then gets expanded to this by cpp: { I_ _ccall_result; StgAddr _ccall_arg1=_B0_; _ccall_result = (((((_ccall_arg1))->_attrs = (0L)))); _B3_=_ccall_result; } (there was some disagreement over whether such a macro was poorly written for not casting its argument; either way, the fact remains that this sort of thing is out there, and convincing the rest of the world to change to make things a bit easier for us is not going to happen.). Possible solutions ================== 1 = One solution is to write a C wrapper around each potentially affected function. I don't think this is very satisfactory as it significantly increases the amount of effort needed to create a binding (rather than just a single foreign import statement you now also need a line in a C file and to make sure the object file is built and linked in correctly). 2 = Surrounding the function with parentheses so the macro doesn't match. The offending line above would be _ccall_result = ((wstandend)((_ccall_arg1))); 3 = I haven't tested this, but I assume you could just generate #undef wstandend before the function call. When to fix the problem ======================= (I'm assuming solution 1 is rejected from here on - if it's the one chosen then the rest is irrelevant) The above gives ways to fix the problem, but there were worries that it could cause a significant performance penalty to always do this, including in some of the bits of GHC implementation. Two possible alternatives come to mind. A = Where a cid is permitted also permit '(' cid ')' B = Before the optional '&' in a C impent, allow an optional "nomacro". The implementation would then make sure you didn't get a macro using solution 2, 3 or some other means. ===== Both A and B allow the programmer to highlight where they cannot trust macros to behave as needed (by ghc -fvia-C at least), so the performance hit is taken only when we can't be sure it is safe not to. ===== In case it isn't clear, I don't like solution 1 (which is what we have at the minute), but would be happy with any combination of {1,2} and {A,B}. Thanks Ian _______________________________________________ FFI mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/ffi