ANN: H98 FFI Addendum 1.0, Release Candidate 9
RC 9 of the FFI Addendum is now at http://www.cse.unsw.edu.au/~chak/haskell/ffi/ The addendum seems to be stable and I like to close Version 1.0. There is only one open question: What to do about "threadsafe"? In the threads discussion, there seemed to be a tendency to not distinguish between "threadsafe" and "safe" after all. Shall we remove "threadsafe" from 1.0? That's what I tend to and will do unless there are strong arguments to retain "threadsafe". Cheers, Manuel -=- Changes since RC 8 * 5.8: `MarshallAlloc.reallocBytes' is no longer permitted on memory allocated with `alloca' or `allocaBytes'. * 6.1: Deinitialisation of the RTS via `hs_exit()' followed by (re)initialisation with `hs_init()' must be supported.
On Wednesday 21 May 2003 1:53 pm, Manuel M T Chakravarty wrote:
RC 9 of the FFI Addendum is now at
http://www.cse.unsw.edu.au/~chak/haskell/ffi/
The addendum seems to be stable and I like to close Version 1.0.
Excellent news. Thanks for all your work on this - I think we ended up with a good design!
There is only one open question: What to do about "threadsafe"? In the threads discussion, there seemed to be a tendency to not distinguish between "threadsafe" and "safe" after all. Shall we remove "threadsafe" from 1.0? That's what I tend to and will do unless there are strong arguments to retain "threadsafe".
I think it should be removed but there should be a section near the start of the document which lists open issues which would include: - bindings for other languages - issues involving threads (i.e., whatever it is that threadsafe was intended to solve). -- Alastair Reid
Some typos: 2 Lexical Structure: "import" shouldn't be a specialid (it's a Haskell 98 reserved word). 5.2 Bits, shift, rotate: replace last sentence to say that for unbounded types (e.g., Integer) rotate is equivalent to shift. 5.2 Bits, definition of bitSize: "have a have a" 5.3 Int and Word: "all type classes for which Int has an instance, this includes the class Bits" isn't right: it includes user-defined instances. I'd suggest "the class Bits and all type classes for which Int has an instance in the Haskell 98 Prelude and standard libraries". 5.5 ForeignPtr: last sentence of first para isn't quite right, as the finalizer is now in the foreign language. 5.5 newForeignPtr: the third sentence is missing some words, probably "is passed". 5.6 StablePtr, data StablePtr a: the 2nd and 3rd sentences aren't quite right: ForeignPtr a is no longer an instance of Storable, and nor is StablePtr a. (But if someone made it so, the behaviour would be perfectly well defined.) Better to drop these two sentences and just say it's not an instance of Storable. 5.8 MarshallAlloc, last para: missing "the" in the first sentence. Table 2: delete HsForeignPtr (not a basic foreign type) and a query: why are there conversions between StablePtr a and (Fun)Ptr a, and HsStablePtr constrained to (void *)?
Ross Paterson <ross@soi.city.ac.uk> wrote,
Some typos: [..]
Thanks for reading the document so carefully!
and a query: why are there conversions between StablePtr a and (Fun)Ptr a,
In tool-generated bindings, it is sometimes more convenient to cast to a Ptr and pass the Ptr.
and HsStablePtr constrained to (void *)?
This is a kludge. Essentially, we would like an abstract type and (void *) is the closest you get in C (and what is typically used in C APIs for the same purpose). It is important to be concrete about the type to fix the storage requirements. Cheers, Manuel
On Thu, May 22, 2003 at 07:05:38PM +1000, Manuel M T Chakravarty wrote:
Ross Paterson <ross@soi.city.ac.uk> wrote,
and HsStablePtr constrained to (void *)?
This is a kludge. Essentially, we would like an abstract type and (void *) is the closest you get in C (and what is typically used in C APIs for the same purpose). It is important to be concrete about the type to fix the storage requirements.
I don't follow you. Why is it necessary to be more concrete than HsInt and HsFloat? We don't know exactly what they are, but we know we can use sizeof, and assign them, etc. Why can't HsStablePtr just be constrained to be a scalar type?
Ross Paterson <ross@soi.city.ac.uk> wrote,
On Thu, May 22, 2003 at 07:05:38PM +1000, Manuel M T Chakravarty wrote:
Ross Paterson <ross@soi.city.ac.uk> wrote,
and HsStablePtr constrained to (void *)?
This is a kludge. Essentially, we would like an abstract type and (void *) is the closest you get in C (and what is typically used in C APIs for the same purpose). It is important to be concrete about the type to fix the storage requirements.
I don't follow you. Why is it necessary to be more concrete than HsInt and HsFloat? We don't know exactly what they are, but we know we can use sizeof, and assign them, etc. Why can't HsStablePtr just be constrained to be a scalar type?
StablePtr are used to export references to Haskell values to C, where they are treated as abstract data. In C one traditionally uses (void *) for that purpose (see "man qsort(3)"). We want to make sure HsStablePtr is not to wide to be passed as an argument to C functions expecting such abstract types (such as qsort(3)). sizeof is of little help here. The C compiler will have allocated a fixed amount of storage when it compiled the C library. Our type fits in there or not. All you can do with sizeof is to add an assertion that aborts the program in case of a mismatch. John Meacham <john@repetae.net> wrote,
There is also uintptr_t and intptr_t, integral types guarenteed to be able to hold a (void *). very handy for storing a token which might be a number or pointer and you want to be able to safely cast between them.
Again I am worried that C libraries, which tend to use (void *) not uintptr_t or intptr_t will mismatch with out definition of HsStablePtr. Cheers, Manuel
On Wed, Jun 04, 2003 at 11:09:43PM +1000, Manuel M T Chakravarty wrote:
StablePtr are used to export references to Haskell values to C, where they are treated as abstract data. In C one traditionally uses (void *) for that purpose (see "man qsort(3)"). We want to make sure HsStablePtr is not to wide to be passed as an argument to C functions expecting such abstract types (such as qsort(3)).
How does HsStablePtr differ from HsDouble in this respect? (except that the C side can do even less with HsStablePtr.) You know it somehow corresponds to a pointer on the Haskell side, but that doesn't seem relevant.
Ross Paterson <ross@soi.city.ac.uk> wrote,
On Wed, Jun 04, 2003 at 11:09:43PM +1000, Manuel M T Chakravarty wrote:
StablePtr are used to export references to Haskell values to C, where they are treated as abstract data. In C one traditionally uses (void *) for that purpose (see "man qsort(3)"). We want to make sure HsStablePtr is not to wide to be passed as an argument to C functions expecting such abstract types (such as qsort(3)).
How does HsStablePtr differ from HsDouble in this respect? (except that the C side can do even less with HsStablePtr.)
HsDouble is guaranteed to be one of C's floating types; hence, all operations on floating types can be applied on values of type HsDouble. If a value of type "float" is passed to a function argument of type "double", the C compiler will insert automatic coercion code by way of C's argument promotion rules automatically. We cannot rely on such promotion rules for pointers.
You know it somehow corresponds to a pointer on the Haskell side, but that doesn't seem relevant.
There is no guarantee whatsoever that HsStablePtr is a pointer on the Haskell side. In GHC, stable pointers are integral indexes into a table of stable values. Cheers, Manuel
On Sun, Jun 08, 2003 at 09:06:07PM +1000, Manuel M T Chakravarty wrote:
Ross Paterson <ross@soi.city.ac.uk> wrote,
On Wed, Jun 04, 2003 at 11:09:43PM +1000, Manuel M T Chakravarty wrote:
StablePtr are used to export references to Haskell values to C, where they are treated as abstract data. In C one traditionally uses (void *) for that purpose (see "man qsort(3)"). We want to make sure HsStablePtr is not to wide to be passed as an argument to C functions expecting such abstract types (such as qsort(3)).
How does HsStablePtr differ from HsDouble in this respect? (except that the C side can do even less with HsStablePtr.)
HsDouble is guaranteed to be one of C's floating types; hence, all operations on floating types can be applied on values of type HsDouble.
I meant to say that you can't pass an HsDouble to a "polymorphic" C function expecting (void *), so why should you be able to pass an HsStablePtr? Maybe you're arguing that otherwise it couldn't be passed to any legacy C function, whereas doubles can, though to different ones.
You know it somehow corresponds to a pointer on the Haskell side, but that doesn't seem relevant.
There is no guarantee whatsoever that HsStablePtr is a pointer on the Haskell side. In GHC, stable pointers are integral indexes into a table of stable values.
Same in Hugs (though that's not a coincidence), which makes it all the stranger that they're treated as pointers.
Dnia wto 10. czerwca 2003 01:00, Ross Paterson napisaĆ:
I meant to say that you can't pass an HsDouble to a "polymorphic" C function expecting (void *),
You can pass a pointer to double. Imagine a hashtable implemented in C. It will most probably store void * as values. You can use it for any concrete value type by storing pointers to values, probably living in malloced memory, unless they already are pointers, in which case it's implicitly convertible to and from void *. Imagine a C API which gives you handles to pictures as opaque values. You are supposed to use its functions only to work on the picture data. You want to store pictures in a hashtable. If it gives you type Picture and doesn't say how the type is represented, you must malloc(sizeof Picture) and store the pointer in the hashtable. But if it explicitly says that Picture is a pointer, or it even uses Picture *, then you can store them without additional wrapping.
so why should you be able to pass an HsStablePtr?
Because we can arrange that you don't need to wrap it in an additional pointer. Even if it was safe to cast them void *, you could not be sure - you can't portably conclude it from the fact that it's an integral value. Why not to provide the convenience? -- __("< Marcin Kowalczyk \__/ qrczak@knm.org.pl ^^ http://qrnik.knm.org.pl/~qrczak/
Ross Paterson <ross@soi.city.ac.uk> wrote,
On Sun, Jun 08, 2003 at 09:06:07PM +1000, Manuel M T Chakravarty wrote:
Ross Paterson <ross@soi.city.ac.uk> wrote,
On Wed, Jun 04, 2003 at 11:09:43PM +1000, Manuel M T Chakravarty wrote:
StablePtr are used to export references to Haskell values to C, where they are treated as abstract data. In C one traditionally uses (void *) for that purpose (see "man qsort(3)"). We want to make sure HsStablePtr is not to wide to be passed as an argument to C functions expecting such abstract types (such as qsort(3)).
How does HsStablePtr differ from HsDouble in this respect? (except that the C side can do even less with HsStablePtr.)
HsDouble is guaranteed to be one of C's floating types; hence, all operations on floating types can be applied on values of type HsDouble.
I meant to say that you can't pass an HsDouble to a "polymorphic" C function expecting (void *), so why should you be able to pass an HsStablePtr?
Because HsStablePtr (in contrast to HsDouble) is used to pass abstract Haskell values to C routines, so that they can pass them around, store them, and pass them back to Haskell. C routines that are meant to handle abstract values usually use (void *). Manuel
On Thu, May 22, 2003 at 07:05:38PM +1000, Manuel M T Chakravarty wrote:
Ross Paterson <ross@soi.city.ac.uk> wrote,
and a query: why are there conversions between StablePtr a and (Fun)Ptr a,
In tool-generated bindings, it is sometimes more convenient to cast to a Ptr and pass the Ptr.
and HsStablePtr constrained to (void *)?
This is a kludge. Essentially, we would like an abstract type and (void *) is the closest you get in C (and what is typically used in C APIs for the same purpose). It is important to be concrete about the type to fix the storage requirements.
There is also uintptr_t and intptr_t, integral types guarenteed to be able to hold a (void *). very handy for storing a token which might be a number or pointer and you want to be able to safely cast between them. John -- --------------------------------------------------------------------------- John Meacham - California Institute of Technology, Alum. - john@foo.net ---------------------------------------------------------------------------
Alastair Reid <alastair@reid-consulting-uk.ltd.uk> wrote,
There is only one open question: What to do about "threadsafe"? In the threads discussion, there seemed to be a tendency to not distinguish between "threadsafe" and "safe" after all. Shall we remove "threadsafe" from 1.0? That's what I tend to and will do unless there are strong arguments to retain "threadsafe".
I think it should be removed but there should be a section near the start of the document which lists open issues which would include:
- bindings for other languages - issues involving threads (i.e., whatever it is that threadsafe was intended to solve).
The introduction already mentions bindings for other languages as an open issue. I have added the following paragraph to cover threads: The second major omission from the present report is the definition of the interaction with multithreading in the foreign language and, in particular, the treatment of thread-local state. Work on this problem is not sufficiently mature to be included into Version 1.0 of the report. Cheers, Manuel
participants (5)
-
Alastair Reid -
John Meacham -
Manuel M T Chakravarty -
Marcin 'Qrczak' Kowalczyk -
Ross Paterson