[MLton] passing a const char **

Matthew Fluet fluet at tti-c.org
Wed Dec 13 07:41:31 PST 2006


At the current time, there is no way to represent a "string vector" 
differently than a "const char **", so you can patch the elaborator to 
allow nested indirect types:

Index: mlton/elaborate/elaborate-core.fun
===================================================================
--- mlton/elaborate/elaborate-core.fun	(revision 4972)
+++ mlton/elaborate/elaborate-core.fun	(working copy)
@@ -781,7 +781,8 @@
            | SOME (c, ts) =>
                 if List.exists (unary, fn c' => Tycon.equals (c, c'))
                    andalso 1 = Vector.length ts
-                  andalso isSome (toNullaryCType (Vector.sub (ts, 0)))
+                  andalso (isSome (toNullaryCType (Vector.sub (ts, 0)))
+                           orelse isSome (toUnaryCType (Vector.sub (ts, 
0))))
                    then SOME {ctype = CType.pointer, name = "Pointer"}
                    else NONE


John Reppy wrote:
> In this particular application (OpenGL shaders) the whole point of 
> passing an array of
> strings is to avoid having to concatenate them, but thanks for the 
> suggestion.
> 
>     - John
> 
> On Dec 12, 2006, at 9:55 PM, Matthew Fluet wrote:
> 
>>
>>> I need to call a C function that takes as an argument an array of 
>>> strings
>>> (with type const char **).  Unfortunately, trying to import the function
>>> with a "string vector" argument type doesn't work.  Is there a good 
>>> reason
>>> for this restriction?
>>
>> If ML object pointers are not represented the same way as C pointer, 
>> then "string vector" doesn't have the same representation as "const 
>> char **".  This is an issue on 64bit systems with smaller ML object 
>> pointers.  It is reasonable to perform the constant time operation of 
>> lifting ML object pointers to C object pointers for the outermost FFI 
>> types, but it isn't constant overhead to coerce a vector of ML object 
>> pointers to a vector of C pointers, so I don't think it is the right 
>> design decision to support it.
>>
>> > Am I going to have to malloc the strings to pass
>>> them as arguments?
>>
>> We need to handle the "const char **" idiom for exece/execp.  Here is 
>> my solution:
>>
>> On the ML side, concatenate all the strings together into a single 
>> vector.  This isn't as expensive as it sounds, since one normally 
>> needs to add a null-terminator to all the ML strings before throwing 
>> it over to the C side.  Also on the ML side, allocate a C_Pointer.t 
>> array and a C_Size.t vector (although, perhaps the latter should be 
>> C_Ptrdiff.t). The C_Pointer.t array is of the same size as the number 
>> of strings, and is initialized to null.  the C_Size.t vector is also 
>> of the same size as the number of strings, and is initialized to 
>> offsets into the concatenated string that correspond to the beginning 
>> of each string.
>>
>> This code can be found in the CUtil.StringVector structure:
>> http://mlton.org/cgi-bin/viewsvn.cgi/mlton/trunk/basis-library/util/CUtil.sml?rev=4898&view=auto 
>>
>>
>> On the C side, fill in the C_Pointer.t array with the C pointers 
>> corresponding to the base of the concatenated string plus the offset.
>>
>> This code, for Posix.Process.exece, can be found at:
>> http://mlton.org/cgi-bin/viewsvn.cgi/mlton/trunk/runtime/basis/Posix/Process/exece.c?rev=4898&view=auto 
>>
>>
>> I'll admit that it isn't as clean a solution as I would like, and 
>> perhaps it is overkill to handle mixed pointer representations.
>>
>>
>>
> 
> 
> 




More information about the MLton mailing list