David,
My situation is slightly unusual so perhaps it's useful/interesting to explain some background. I'm working on support for GLib/GTK in SML which involves a significant number of calls to C functions. These C functions need wrapping to provide a suitable ML interface for various reasons. One such reason is for C string matters relating to optional strings using null pointers, in place modification and allocation which the caller must free. Given the number of C functions and the requirement for implementation across different SML compilers, I am creating a portable ML wrapping layer to reduce compiler-specific ML. For C strings, there is a module which provides various wrapping functions with a pointer-like abstract type cstring. It is this cstring type that has a null value.
So, on the one hand, I can actually just remove val null from the interface. A null cstring can be constructed via another function. However, it seems natural to have a null value. On the other hand, using vol option to implement a possibly-null pointer works (taking NONE as null and SOME v as possibly-null). However, it seems perverse having an ML datatype for nothing more than an actual C pointer.
Either way, a null pointer is going to create a new vol each time (as I understand it) which involves a small amount of allocation. Perhaps a persistent null : vol is worthwhile just from an efficiency perspective?
Regarding vol comparison, I actually meant comparison of the underlying C pointers. This was only motivated by considering the implementation of comparison with null, so probably not worth exploring.
Thanks, Phil
On 15/11/11 15:30, David Matthews wrote:
Phil, I think it could be possible to provide CInterface.null as a persistent vol pointing to a value containing (void*)0. I know that seems a contradiction but it should be possible. I'm just not sure it's necessary. Why do you need to have "null" and "isNull"? Have you considered instead building converters between the C data structure and ML and doing everything within ML. There's example of this in mlsource/extra/CInterface/Examples/ForeignTest.sml which converts a simple tree structure:
(* Example of creating a conversion for a datatype. *) datatype intTree = NullTree | Node of {left: intTree, right: intTree, valu: int};
(* The corresponding C structure is typedef struct _tree { struct _tree *left, *right; int nValue; } *tree; *)
On the your question about equality for vols: it's possible that there could be an equality test but I'm not sure it would be very useful. All it would do would test whether they were the same vol but that wouldn't tell you whether two vols contained the same C data.
Regards, David
On 13/11/2011 21:35, Phil Clayton wrote:
On 11/11/11 20:18, Phil Clayton wrote:
I am currently implementing type t val null : t val isNull : t -> bool where type t = CInterface.vol. There is no problem doing this but I wondered whether I could improve the CInterface structure to avoid annoying little C library functions.
I have realized that C functions are not necessary to implement these - just to toClong and fromClong:
val null = toClong 0 fun isNull v = fromClong v = 0
Would it be at all controversial to include null : vol in CInterface?
For a different reason, this could still be useful. I had forgotten that volatiles do not persist in saved states or executables (it should have been obvious from the name) so I can't see how to create such a null value to implement
val null : t
where type t = CInterface.vol. (There is nothing volatile about null really.)
Perhaps the best approach here is to implement with type t = CInterface.vol option, with NONE representing null.
Phil
polyml mailing list polyml@inf.ed.ac.uk http://lists.inf.ed.ac.uk/mailman/listinfo/polyml
polyml mailing list polyml@inf.ed.ac.uk http://lists.inf.ed.ac.uk/mailman/listinfo/polyml