[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