*sigh* I never thought that the "last words" on this topic would be easy,
but on the other hand I never imagined that ISO/ANSI C, POSIX, Unicode,
ISO-10646, Ada95, OCaml, persistent functions, etc. will pop up... It's
surely worth having a look at things other people have done, but here are
some instant thoughts before I delve into The Net.
Regarding 1. Mapping Haskell types to C types:
===========================================================================
1) To be honest, I don't know enough about char/wchar_t/Unicode/ISO-10646
to make suggestions here. Could somebody more knowledgeable make a
proposal how these should be handled in the FFI? Keep in mind that this
affects the reverse mapping, too, and that using good old C Strings
should be easy.
2) It should be *guaranteed* that HsStablePtr and HsAddr are mapped to
void* for the reason mentioned by Manuel. Nevertheless, these types are
not useless, they serve as documentation what the pointer should mean.
3) If ISO C has long long (don't know, my copy of Harbison/Steele doesn't
mention it), Int64/Word64 should be made mandatory.
4) The include file's name is HsFFI.h, not simply ffi.h.
5) Let's explicitly state that Hs{Int,Word}{8,16,32,64} and ISO C's
{,u}int{8,16,32,64}_t are the same. Having the HsFoo names around is
nevertheless handy because it is not clear to me what #include one can
use in a portable way (e.g. there is no stdint.h on HP-UX 10.20).
6) Add HsBool with a mapping to an arbitrary integral C type, see Fergus'
point about a Haskell API. (Should we guarantee that False maps to 0 and
True to something <>0?)
Regarding 2. Mapping C types to Haskell types:
===========================================================================
1) Add the following type synonyms to module FFI (if there is no
corresponding Haskell type, the implementation should use the "closest"
one):
Haskell type | C type
-------------+-------------------
CLLong | long long
CULLong | unsigned long long
CLDouble | long double
2) The ANSI types are a little bit more complicated than I thought. So here
is my first shot:
* The following table contains type synonyms for integral types:
Haskell type | C type
-------------+-------------
CPtrdiff | ptrdiff_t
CSize | size_t
CSigAtomic | sig_atomic_t
CWchar | wchar_t
* The following table contains type synonyms for numeric types:
Haskell type | C type
-------------+-------------
CClock | clock_t
CTime | time_t
* fpos_t may be a complex type, but it is only used as fpos_t*,
i.e. a pointer to a buffer. So we define CFpos as an abstract type,
which is an instance of Storable. This way a buffer can be
allocated (e.g. buf <- mallocElem (undefined::CFpos)), and its
address passed via the usual Addr type. Although this is not
extremely elegant, it is a simple way to use fpos_t without adding
special knowledge about it into foreign import/export.
* jmp_buf is almost the same story as fpos_t, with the small
difference that always jmp_buf and not jmp_buf* is
used. Nevertheless, on every architecture I had a look at (Linux,
HP-UX, Solaris, OSF) it is a pointer/array. So we can use an
abstract type CJmpBuf, which is an instance of Storable.
* div_t/ldiv_t are only used as return values of div/ldiv. For
completeness one could add something like
data CDiv = CDiv Cint Cint
data CLdiv = CLdiv CLong CLong
and make CDiv/CLdiv instances of Storable. But IMHO it is hardly
worth the trouble.
* The application programmer never uses FILE, but always FILE*, so
there is no need for CFile. Addr can be used instead (modulo the
typed vs. untyped pointer dispute).
* I can't see any use for a Haskell type corresponding to va_list. It
is only used in the macros(!) va_start, va_arg, and va_end.
3) I don't think that we should care about this ancient far/near pointer
stuff. It is already enough that there are different calling conventions
on Windows platforms.
4) IMHO it *does* make sense to have a C mapping for
StablePtr (b -> [Maybe Int] -> IO (Integer, b))
Why should stable pointers be restricted to basic types? The full range
of types is very useful, e.g. for bindings of callback-based C APIs,
which associate arbitrary values with a callback.
Doing some name mangling from a Haskell type can be a tricky business,
e.g. one must differentiate between
StablePtr (a, Maybe b)
StablePtr (a, Maybe a)
StablePtr (a, MyOwnModule.Maybe b)
...
This is certainly doable, but is this really worth the trouble? I'm not
sure and would definitely like to hear some opinions on this topic.
Cheers,
Sven
--
Sven Panne Tel.: +49/89/2178-2235
LMU, Institut fuer Informatik FAX : +49/89/2178-2211
LFE Programmier- und Modellierungssprachen Oettingenstr. 67
mailto:[EMAIL PROTECTED] D-80538 Muenchen
http://www.informatik.uni-muenchen.de/~Sven.Panne