One of HaskellDirect's front-ends support DCE IDL, which is syntactically extremely close to C prototype and type declarations in the sense that a C header file can be viewed as low-quality IDL input.
HaskellDirect supports the reading of header files together with a number of mechanisms to help you improve on the information that header file declaration conveys. To elucidate how HaskellDirect can be used, here's a set of steps you will commonly have to go through to import into Haskell the functionality specified in a header file.
module CoolAPI {
#include "CoolAPI.h"
};
ihc, using the following
options:
ihc -fhs-to-c CoolAPI.idl -cpp -I/extra/include/path/needed
i.e., stating that you're generating stubs that let's you
call C functions from Haskell (-fhs-to-c), enable the
use of the C pre-processor plus any configuration of the
include search path that might be needed.--hugs to the command-line.By following the above three steps, HaskellDirect should have
generated CoolAPI.hs, which contains the necessary
type and function stub definitions. However, more often than
not, these stubs are less than satisfactory, for a number of
reasons:
-fexclude-system-includes.
char* getenv(char*);
HaskellDirect generates:
getenv :: Ptr Char -> IO (Ptr Char)
From reading the documentation of the function you know
that the pointers in question are null-terminated character strings,
but there's no way of informing HaskellDirect that this is the
case, at least not via the header file. IDL does supply you with
the capabilities to specify this, through its string
attribute:
[string]char* getenv([in,string]char *arg);
but requiring the user to convert the header file to IDL is not
a practical proposition in most cases. So, to support the user
here, HaskellDirect has got support for Attribute Specification
Files (ASFs), which let's you specify the attributes of a function
separately from its prototype/declaration. For information on
how ASFs lets you improve upon the quality of the generated stub
code, see
Section
Off-line attribute specification.
#defines that the header file contained.
There are no shrink-wrapped solutions to this one (at least not
yet.) Current alternatives are:
-dM),
to list them all. Convert this list into corresponding
IDL const declarations, either through a simple
script or by-hand.#defines to const
declarations. With that patch added, automatic conversion of
#defines into equivalent Haskell defintions becomes possible.
[It is my intention to forward this patch to the GNU CPP
maintainers to have it considered for inclusion, as it serves a useful
role outside our (small) sphere.]-fwinnow-defns or -fonly-remove-defns
together with an ASF file. For instance, assuming your header
file contains prototypes for functions f and g
but you're only interested in f. To achieve this you
supply an ASF (via the option --asf=) containing the
following on-liner:
f:
and compile up the stubs using:
ihc -fhs-to-c -cpp CoolAPI.idl --asf=CoolAPI.asf -fwinnow-defns
Since g isn't mentioned in the ASF, it will be ignored
since -fwinnow-defns will only generate stub code for
definitions mentioned in the ASF file. Notice that if f
uses any locally defined types, they will also be included in
the generated output.
In the cases where it is simpler to name the defintions you want
to exclude from the set of generated Haskell stubs,
-fonly-remove-defns is your friend. For the above
example, you would then supply an ASF listing the functions
you want to omit:
g=
and feed that one-line ASF to HaskellDirect along with -fonly-remove-defns.As a parting remark, it is the author's experience that it is often easy to fall into the trap of spending lots of effort in trying to supply the set of IDL attributes that makes the generated stubs look just right to the Haskell programmer. If you find yourself in this situation, it may be worth considering whether you should instead shift some of the responsibility of providing a Haskell-friendly veneer to the external API into Haskell itself, i.e., write the impedance matching code yourself.