[racket] FFI question: problem passing a cstruct to a function for output

From: Thomas Chust (chust at web.de)
Date: Thu Jul 21 09:32:11 EDT 2011

keydana at gmx.de wrote:
> [...]
> I need to define a function
> boolean OCI_GetStruct (OCI_Resultset * rs, void * row_struct, void * row_struct_ind)
>  that takes 2 structs for output, and these have to be generic structs, not some define-cstruct defined concrete type; so I've tried passing the type in to the function and generating an output argument with (_ptr o <type>):
> (def-ocilib getstruct OCI_GetStruct : (resultset_ptr structtype indtype) :: (resultset_ptr : _pointer) (struct_ptr : (_ptr o structtype)) (ind_ptr : (_ptr o indtype)) -> (result : _bool) -> (and result (values struct_ptr ind_ptr)))
> Unfortunately, on execution I get an error
> Msg: "OCI-21560: argument 3 is null, invalid, or out of range\n"
> [...]

Hello Sigrid,

the declaration of the wrapper function looks correct. For the ind_ptr
argument you could actually pass an array of booleans instead of some
structure, if I interpret the OCI library documentation correctly [1],
but that is just a cosmetic point.

I consider it likely that the failure is not directly related to your
Racket code snippet.

> [...]
> One point that's not clear to me - the struct pointers are declared as void * in the function declaration - do I have to do something special for that?
> [...]

A void * in C is just a pointer with unknown target type. It is
conceptually a supertype of any concrete pointer type whose target type
is known. Machine representation and calling conventions are the same
for all pointer types regardless of their target type so you don't have
to do anything special here.

> [...]
> Otherwise, I'd be very grateful for any hint, if my Racket code is wrong somehow - or otherwise, an idea how I might proceed here (some way to debug FFI calls)?
> [...]

For debugging the native code you can run Racket inside gdb, set signal
handling to ignore the segmentation faults triggered by Racket's memory
management mechanisms and set breakpoints in the native functions you
are interested in.

However, personally I wouldn't invest too much time in getting this API
call to work, if there is no compelling reason to use it. Since the OCI
library cannot check whether the data buffers passed to OCI_GetStruct
have the correct memory layout and since the correct layout further
depends on external factors that can neither be determined statically by
the caller of the library function before the program is executed nor be
reliably controlled under all circumstances, I think that this whole API
function is quite error prone. I would prefer to use the functions that
allow typed access to single cells of the result set, like OCI_GetString
or OCI_GetInt.



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

Posted on the users mailing list.