[racket] FFI: problems using (_list i _string)

From: Thomas Chust (chust at web.de)
Date: Sun Jun 5 07:04:11 EDT 2011

2011/6/5 keydana at gmx.de <keydana at gmx.de>:
> [...]
> The c function is described as
> boolean OCI_BindArrayOfStrings(OCI_Statement * stmt, const mtext * name,
> dtext * data, unsigned int len, unsigned int nbelem)
> where mtext and dtext are aliases for char, the way the library was
> compiled, the second-but-last argument has to indicate the length of the
> longest string in the array, and the last argument has to be 0 apart from a
> special case not applicable here.
> I've defined it as
> (def-ocilib bindstringarray OCI_BindArrayOfStrings : (stmt_ptr : _pointer)
> (name : _string) (data : (_list i _string)) (maxstrlen : _uint =
> (getmaxlength data)) (no : _uint) -> (result : _bool))
> where maxstrlen gives the length of the longest list member.
> [...]

Hello Sigrid,

if dtext is actually an alias for char, as you write, then the
signature of the C function implies that it expects a string, not a
list of strings, as its third argument.

The second problem with the binding definition is that it doesn't
convey any information about the length of the list to the C function,
which is almost certain to cause trouble. Judging by your description
of the C function's contract, simply adding a #f to the end of the
list before passing it to the marshaller should do the job here: Just
replace (data : ...) by (data : ... = (append data '(#f))).

Finally, when passing ephemeral data like this array and the string
pointers it contains to C, one has to be careful that the Racket
garbage collector doesn't interfer with assumptions made on the C side
about the incoming data: If the function doesn't copy the data but
simply stores the pointers somewhere and returns, the data may be
garbage collected before it is used again in some other C function,
which of course will fail miserably in that case.

> [...]
> I also tried using
> (data :  (_list io _string (length data))
> instead, in order to check the correctness of the input strings, putting
> them out as part of the functions return values, but for doing (length data)
> I get the error
> length: expects argument of type <proper list>; given #<cpointer>
> so here data seems to be a c type, not a racket list anymore...
> [...]

I think that in the lexical scope where the expansion of the _list
syntax inside the _fun syntax places the output argument length
computation, the name of the output argument is bound to the raw
pointer from C. You can circumvent this by using a different name for
the argument of the Racket wrapper procedure and the argument of the C
function — check the description of the _fun syntax for the maybe-args
part.

Ciao,
Thomas


-- 
When C++ is your hammer, every problem looks like your thumb.



Posted on the users mailing list.