FFI proposal: allow some control over the scope of C header files

Duncan Coutts duncan.coutts at worc.ox.ac.uk
Fri Apr 21 07:31:10 EDT 2006


One problem that people writing FFI bindings often run into is that they
do not understand exactly where C header files are required to be
available.

The easy case is importing some C function defined in a well known and
widely available C header file (eg gtk/gtk.h). In this case we just make
sure that header is available for compiling every module in the package
and add that header file to the package info file (or .cabal file) so
that every module that uses the package will have the C header
available. In this case there is no problem with C calls being inlined
outside of the module which imported them since the C header file will
be available everywhere.

The tricky case is that people often use "private" header files that are
#included when compiling a module/package but are not installed along
with that package and so are not #included when compiling client
modules. Most of the time this works, however the Haskell compiler is
allowed to inline across modules and if it chooses to inline the C call
into a client module then things will break. Sadly it still compiles and
sometimes even works since C allows calling a C function without a
prototype. However occasionally it's going to break horribly.

Allowing us to limit where the C headers will be required would be very
useful. Sometimes it is very convenient to have private header files
that will not be installed with the package. It is also sometimes the
case that it's much more convenient to not require that the user has a
set of C header files installed to be able to use a library package.
Examples of this include some windows packages, eg DriectX where it's
rather inconvenient to require that users have the MS DirectX SDK
installed.

Currently GHC has a de-facto way of limiting the required scope of C
header files to a module - by using the standard FFI syntax (!). I know
people are already using this trick to allow the use of private header
files.

This issue also touches on the related issue that the way of specifying
C header files in the FFI spec is not really optimal. GHC implements a
couple other methods and these are probably used more that the method in
the FFI spec.

So I suggest that we briefly consider some possibilities for extending
control over where C header files will be needed and perhaps also for
specifying what C header files are needed in the first place.

I think we'd want to be able to specify that a C header file not
"escape" a module boundary and probably we'd also want to be able to ask
that it not escape a package boundary (though this may be beyond the H'
spec since Haskell does not talk about packages).

It would also be convenient to be able to specify that a module needs a
particular C header file rather than having to specify it in each
foreign import decl. Currently this can be done by cabal in a
compiler-specific way (it uses ghc's -#include command line mechanism)

It's a reasonable question to ask if specifying a C header file should
go in the module source code or elsewhere (eg a .cabal file) since
afterall we don't specify search paths etc in the module. I'd say that
it is right that the name of the header file be in the module source
code and that the search paths etc be external.

So some syntax off the top of my head:

foreign import cheader module-local "foo/bar.h"

I think there are 3 possibilities for the C header escape/scope setting
(which should probably be manditory rather than optional):
module-local
package-local (extension for compilers that have a notion of a package)
global

this should allow us to automatically check what C headers are needed by
client modules.

Duncan



More information about the Haskell-prime mailing list