On 27-Mar-2000, Sven Panne <[EMAIL PROTECTED]> wrote:
> Yes, C programmers are not that lazy. :-)
>
> > What if you want to pass an unevaluated closure (e.g. so that you
> > can later pass it back to Haskell and then evaluate it)?
>
> This is what stable pointers are for and they are covered by the
> mapping.
OK, that makes sense.
> > What about Bool, lists, tuples, Array, Integer, Maybe, Either, ...?
>
> Bool and Integer are a slightly different case: Boolean values *are*
> primitive, but there is a plethora of representations on the C side,
> differing in bit size, signedness, values... So IMHO it's better to
> let the programmer explicitly write a one-liner for what the API in
> question needs than to give a rather ad-hoc mapping.
What if the API in question is a Haskell API, that you want to access
from C? In that case it makes sense for the FFI to just pick one,
rather than requiring the programmer to choose.
> > Providing a C equivalent for Dynamic would help a bit; you could
> > use that as a catch-all. But of course Dynamic itself is not yet
> > part of standard Haskell.
>
> Is there anything special to Dynamic that isn't covered by the above
> mapping plus a higher-level marshaling library?
No, I think you are right -- stable pointers will suffice.
> HsStablePtr should be void*, too, for the reason mentioned in my
> previous mail.
It would be fine to have a `typedef void *HsStablePtr'. But it is important
that you do not lose static type information when exporting Haskell functions
to C. So a parameter of type `StablePtr Int' on the Haskell side should get
converted to a pointer to an opaque struct type, e.g. `struct HsStablePtrInt *'
in C, not to just plain `HsStablePtr'.
We did something quite similar in the Mercury FFI, mapping all non-primitive
types to a single type `Word'. This was a big mistake. We have been
paying for that lack of static type information ever since, and in my
experience (having reviewed, written and/or debugged lots of code which uses
the Mercury FFI, which we use extensively in the implementation of the Mercury
library and runtime system) the cost has been quite high indeed.
This is also one of the things which is relatively easy if you do it
right in the first place but (for backwards compatibility reasons,
and due to the large amount of code which depends on it)
quite difficult to change afterwards.
If there was just one point I could stress, based on my experience
with the Mercury FFI, this one would be it. Preserving type safety
across the FFI is very important.
> > ANSI/ISO C is pretty widespread these days; I think it would be worth
> > including `long double'. The Ada 95 standard included
> > `Interfaces.C.long_double', and that was 5 years ago. These days it's
> > quite hard to find a pre-ANSI C compiler.
>
> ... unless you have HP-UX and didn't purchase the the optional ANSI
> C compiler. >:-(
I thought the only purpose of the non-ANSI HP-UX C compiler
was so that you could build and install GNU C! ;-)
> > > 3) Addr can be used for all kinds of C pointers.
> > That approach compromises strong typing.
>
> C compromises almost everything.
Nevertheless, the less compromises made, the better.
> > It would be better to have a polymorphic Haskell type corresponding
> > to C pointers.
>
> We had a discussion about this topic some time ago and were reluctant
> to add this without some previous experimentation.
Ada 95 has a generic (i.e. parametric) type corresponding to C pointers.
So there is some prior art in other languages.
> Perhaps some Haskell systems will implement
>
> data Ptr a -- opaque type
>
> as an extension. BTW, Ptr is probably not fully polymorphic, e.g.
> what should be the mapping for
>
> Ptr (b -> [Maybe Int] -> IO (Integer, b))
> ?
It should be a pointer to whatever the mapping for
`b -> [Maybe Int] -> IO (Integer, b)' is.
> > > 4) The following standard types are so ubiquitous that they
> > > should probably be included, too: (any further types wanted?)
> > [...]
> > Here's a full list of the types defined by ANSI/ISO C (89)
> > and POSIX.1:
>
> Are there online-references for these standards?
There are some online lists of the names of the functions, types, and other
entities that these standards define, e.g. at
<http://www.opengroup.org/public/tech/unix/apis.html>, but these lists do not
discuss their semantics. The standards themselves are not freely available
online. You can buy them online, but at fairly exorbitant prices.
An electronic version of the C++ standard is available for $US18; check the
comp.std.c++ FAQ list at http://reality.sgi.com/austern_mti/std-c++/faq.html
for details. There is some hope that the new C 99 standard will also
eventually be available for a similar price.
> > POSIX <dirent.h> typedef DIR
> > [...]
> > POSIX <unistd.h> typedef ssize_t
>
> Those should probably go into the Posix libs, not the basic FFI lib.
Yes, that is a good idea.
> > > [...] 3. Byte order [...]
> > Yes, there are more esoteric ones.
>
> Could you give examples? I know that there are e.g. 4! = 24 ways to
> arrange the bytes of a 32bit int, but...
Well, the GNU C source has numerous different configuration macros
regarding endianness, e.g.
BYTES_BIG_ENDIAN
WORDS_BIG_ENDIAN
FLOAT_WORDS_BIG_ENDIAN
BITS_BIG_ENDIAN
Apparently these do not always agree.
For example, BYTES_BIG_ENDIAN and WORDS_BIG_ENDIAN
disagree on the 1750a, fx80, gmicro, and pdp11 targets.
> > Furthermore it's generally a bad idea to write code that relies on
> > byte ordering. I don't see any reason for the Haskell FFI to
> > encourage this.
>
> It's not a matter of encouragement, but a matter of necessity: There
> are a lot of binary file formats out in the real world, and you really
> need to know if some swapping is needed or not.
You can read/write things byte at a time, and choose whichever byte order you
want. For example, the following routine reads in a 16-bit unsigned integer
encoded in big-endian format from a file.
/* error checking omitted in the interests of simplicity */
uint16 read_big_endian_uint16(FILE *fp) {
uint8 c0, c1;
c0 = getc(fp);
c1 = getc(fp);
return (c0 << 8) | c1;
}
Note that this code works regardless of the endianness of the CPU it is
running on.
--
Fergus Henderson <[EMAIL PROTECTED]> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger [EMAIL PROTECTED] | -- the last words of T. S. Garp.