Modified proposal for default decls
fjh at cs.mu.oz.au
Mon Feb 26 11:49:13 EST 2001
On 26-Feb-2001, Simon Peyton-Jones <simonpj at microsoft.com> wrote:
> a) What is necessary to uniquely identify the thing you want to call.
> In C this is just a single identifier; in Java, it's a fully
> method name, plus the method type. Other languages doubtless
> lie between
> b) What is necessary to allow the compiler to typecheck the
> foreign import/export. In part, we seek #includes so that
> in the via-C route the C compiler will compare the call with the
> prototype, and complain if they don't match. But this is an
> thing. In principle, the Haskell compiler could consult type info and
That's true, in principle. However, the vast majority of C compilers
don't store the necessary type info. On the other hand, all C
compilers support header files. Using header files and generating C
wrappers for imported functions is the only portable way of doing type
checking of foreign import for C, I'm pretty sure.
> The important thing is that there's enough info to get from
> the thing-being-called to the type-of-the-thing-being-called.
> c) What is necessary for particular compilers, compiling in a particular
> to generate the right code. In particular, GHC compiling via C. GHC
> can't generate prototypes, because they might be #included. GHC can't
> omit prototypes unless prototypes are guaranteed to be #included.
> Hence the motivation to specify #include stuff.
Many C interfaces contain a significant number of macros. And C is
one of the most widely used languages that we want to interface with.
So it seems to me that any FFI which aims to provide *good* support for
C ought to provide a way of accessing C macros.
To handle macros, you need to know which header files are involved,
since the same macro can have different definitions in different
header files. And, since the definitions of the macros may well
contain compiler-specific C extensions, I'm pretty sure that the only
portable way of handling those is to generate a C function wrapper
that calls to macro, and compiler that with the C compiler on it.
> Notice that
> a) is essential
> b) is desirable, but not implemented at all
Well, it is implemented in the Mercury compiler; that's not a Haskell
implementation, of course, but I don't think the differences between
Mercury and Haskell have much significance to the design or
implementation of this aspect of the FFI.
It's a good idea to avoid standardization on something before it
has been implemented, in case it turns out to be unimplementable,
or to have significant problems that remained undiscovered until
it was implemented. But given that we've been using this approach
with C header files in the Mercury compiler for a long time, I think
that is unlikely in this case.
So for any Haskell implementation that wants to be able to provide
convenient interfacing with C macros and to type-check C imports,
and wants to be able to do this with arbitrary C compilers,
the Haskell implementation will need to know which headers need
to be included.
You're right that Haskell implementations which only interfaces
with a specific C implementation (or a specific set of them)
can do things differently. But I'm not sure that is the right
thing to focus on.
> In particular, we propose to stick to a mild variant of the current FFI
> foreign import ccall "gtk:foo" foo :: Int -> IO Int
> * The "gtk:foo" is a string in language-specific format
> that uniquely specifies the thing being called.
> * The "gtk:" part is a concession to (b). It specifies a C package
> from which
> this procedure comes. There is then some compiler-specific mechanism
> for mapping the name of a C package to the location of its header
> files and
> .o file.
I could probably live with that.
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
| of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp.
More information about the FFI