ANN: H98 FFI Addendum 1.0, Release Candidate 10
Alastair Reid
alastair at reid-consulting-uk.ltd.uk
Mon Jun 2 10:52:16 EDT 2003
> Using `newtype T = MkT Int8' or equivalent only works for foreign data
> types whose representation is known. How do you deal with C's "time_t",
> for example? Or with C "struct" types? The user doesn't want to make
> non-portable assumptions about what padding the C compiler is going
> to insert.
The usual way is to use some autoconf magic or the hsc2hs preprocessor to
figure it out. The key part of fptools/aclocal.m4:FPTOOLS_CHECK_HTYPE
is this program:
typedef $1 testing;
main() {
FILE *f=fopen("conftestval", "w");
if (!f) exit(1);
if (((testing)((int)((testing)1.4))) == ((testing)1.4)) {
fprintf(f, "%s%d\n",
((testing)(-1) < (testing)0) ? "Int" : "Word",
sizeof(testing)*8);
} else {
fprintf(f,"%s\n",
(sizeof(testing) > sizeof(double)) ? "LDouble" :
(sizeof(testing) == sizeof(double)) ? "Double" : "Float");
}
fclose(f);
exit(0);
}
> But to deal with cases like the ones mentioned above,
> Mercury also allows the user to declare how such types are
> represented in foreign languages, using `pragma foreign_type'
>
> declarations:
> :- pragma foreign_type("C", t, "some_c_typename").
>
> The Mercury compiler will generate appropriate glue code to marshal and
> unmarshal values of that type.
How does it figure out what concrete type to use? Does it use trial
compilations a la autoconf?
> In fact, the "data Int" declaration need not even be physically
> present; the implementation could just insert it in the Prelude
> automatically. (That's what the Mercury implementation does for its builtin
> types.)
Hugs used to insert it automatically but we found that putting the
declarations in the Prelude source code:
1) Made the source closer to the report and made the Prelude
a little easier to understand.
2) Reduced the amount of magic required in the compiler.
--
Alastair
More information about the FFI
mailing list