Summary of current change suggestions

Manuel M. T. Chakravarty chak at cse.unsw.edu.au
Wed Feb 21 00:01:48 EST 2001


malcolm-ffi at cs.york.ac.uk wrote,

> I think we're all agreed now on the desirability of tweaking the FFI
> to permit
> 
>   (a) arbitrary new foreign languages to be added;
> 
>   (b) the "foreignname" specifier to be (potentially) richer, depending
>       on the particular foreign language in question;
> 
>   (c) abstraction of common header/linklib information to a single
>       new sort of decl.
> 
> For backwards compatibility, I suppose on (b) we are going to have
> to continue to allow double-string specifiers of the form
> 
>     foreign import "linklib" "cname"  hname  :: type
> 
> for some time, although that form would be deprecated from now on?

Yes, that's how I see it.

> We know mostly what the richer form of the "foreignname" specifier
> will be for Java, and in any case we can leave that design to SPJ+EM.
> However, we have also heard one or two half-hearted suggestions to
> enrich the "foreignname" string for C as well.  For instance, Manuel
> suggested "Gtk: gtk_new_window".  Is anyone convinced that this
> is a good route for C, or should we settle instead on getting (c)
> right, leaving the "foreignname" untouched for now?

We might be able to combine the two - see below.

> As far as (a) is concerned, we have three decisions to make:
> 
>   (1) Do we use quotes around the language name or accept a simple
>       varid?  E.g. "java" vs java.  As Marcin points out, the names
>       of the languages C and C++ are not varids, so would need to
>       be enclosed in quotes.  On the other hand, see decision point
>       (2) below.
> 
>   (2) The actual names for languages or calling conventions.  Manuel
>       suggests a change from naming the calling convention to naming
>       the foreign language.  This is somewhat attractive.  However,
>       I think many languages have a simple C-callable interface and
>       we don't need to know anything more about the actual language.
>       If this is true, I think we should continue to name the calling
>       convention rather than the language.  Hence, the names  ccall
>       and  stdcall  might be retained,  java  can be added.  If anyone
>       actually comes up with a C++ binding, a name like cplusplus
>       (for instance) seems good enough to me.  This also has the
>       advantage of backwards compatibility, which incidentally would
>       force decision point (1) above towards no-quotes.

I think, I retract my proposal to change ccall to c (you
convinced me).  Let's just stick with the simple varids.

>       Incidentally, the intention would _not_ be that all compilers
>       must support all foreign languages.  As at present, only
>       the ccall convention is mandatory.  Any other named calling
>       convention should be parsed, but if the compiler doesn't support
>       it, a warning (at least) should be issued.  In that situation,
>       it is unclear whether the compiler can actually generate sensible
>       code.  (At the moment, I think the FFI standard says if your
>       platform doesn't support stdcall, code should default to ccall?
>       Obviously that doesn't scale well to java for instance!)

I think, when the compiler supports an unsupported calling
convention it should abort.  stdcall defaulting to ccall is
IMHO just a hack.

>   (3) Where do we allow the language specifier?  In my opinion,
>       definitely in foreign import and export decls.  This is at
>       minimum for backwards compatibility, but looking forward to the
>       day when someone writes FFI code for more than one language in
>       the same module (eek!), it will be needed there.  For the same
>       reason, I would argue that it belongs in the new kind of decl
>       required for (c).

I agree.  In fact, I quite liked one of the proposals that
you made earlier, namely

	foreign library C    "<ncurses/curses.h>" "-lcurses"
	foreign library java "blah" "blah"

	foreign import C    "curses_function" cf :: Int -> IO Int
	foreign import java "java.blah.*/foo" jf :: Int -> IO Int

I also like Marcin's proposal, but I guess it is just too
far away from what we have and quite same work to implement.

So, how about the following.  Keep everything string based.
A module can have one "foreign defaults" declaration per
calling convention, which specifies a string.

  foreign defaults ccall "<gtk/gtk.h>: "
  foreign defaults java  "java."

Now all foreign declarations that want to inherit this
string have their "foreignname" string starting with a '*'
(or whatever symbol you prefer)

  foreign import ccall 
    "*gtk_new_window" newWindow :: CInt -> IO (Ptr Window)

  foreign import java "*blah.foo" jf :: Int -> IO Int

Otherwise, they can override the default by using a full
specification:

  foreign import ccall 
    "<glib/glib.h>: g_timer_start" timerStart :: Ptr Timer -> IO ()

It would be nicer to do without a special symbol indicating
the use of the default, but I guess, this will always lead
to ambiguous situations.

This is, of course, a lot less flexible than what Marcin
proposed, but it would be very simple to implement and is
more or less backwards compatible.

I am not so sure anymore about the specification of link
libraries for C.  It wouldn't be a problem, because we can
always extend the "foreignname", eg, something like

  "<glib/glib.h>; glib: g_timer_start"

However, it usually doesn't help much, to link to GTK+, you
need to specify use

  -L/usr/lib -L/usr/X11R6/lib -lgtk -lgdk -rdynamic -lgmodule -lglib -ldl -lXi -lXext -lX11 -lm

which doesn't seem attractive to include in the Haskell
source.  Moreover, the flags are system dependent.  They
also can't be cleanly handled with #ifdefs, as the only
guarantee that GTK+ gives is that when you execute the
command `gtk-config --libs', it will give you all the right
options.

So, as Marcin pointed out, the only use for a library object
spec for ccall is so that interpreters know which handle to
pass to dlsym().  I am not too fond of the idea that the
interpreter has to try a dlsym() on all library objects that
it did dlopen().  Or is this maybe not too bad?

Cheers,
Manuel




More information about the FFI mailing list