[racket] FFI Pass/Return By Value

From: Jens Axel Søgaard (jensaxel at soegaard.net)
Date: Tue Jun 5 04:31:30 EDT 2012

I am not 100% sure this is the correct reason for the segmentation fault,
but is worth examining.

Even though it is perfectly legal C to return structs as values, there
seems to be more than one way of implementing it. This is in turn
implies that one must compile the library in question with options
that works with what ffilib expects.

More detail from http://www.delorie.com/gnu/docs/gcc/gcc_121.html:


When compiling functions that return structures or unions, GCC output
code normally uses a method different from that used on most versions
of Unix. As a result, code compiled with GCC cannot call a
structure-returning function compiled with PCC, and vice versa.
The method used by GCC is as follows: a structure or union which is 1,
2, 4 or 8 bytes long is returned like a scalar. A structure or union
with any other size is stored into an address supplied by the caller
(usually in a special, fixed register, but on some machines it is
passed on the stack). The machine-description macros STRUCT_VALUE and
STRUCT_INCOMING_VALUE tell GCC where to pass this address.

By contrast, PCC on most target machines returns structures and unions
of any size by copying the data into an area of static storage, and
then returning the address of that storage as if it were a pointer
value. The caller must copy the data from that memory area to the
place where the value is wanted. GCC does not use this method because
it is slower and nonreentrant.

On some newer machines, PCC uses a reentrant convention for all
structure and union returning. GCC on most of these machines uses a
compatible convention when returning structures and unions in memory,
but still returns small structures and unions in registers.

You can tell GCC to use a compatible convention for all structure and
union returning with the option `-fpcc-struct-return'.


See also the answer by tonylo at:

/Jens Axel

2012/6/5 Vince Kuyatt <vince.raiken at gmail.com>:
> I am having a strange issue to do with making an FFI binding to some
> simple C functions which immediately result in a segmentation fault.
> In these functions, all arguments are pass by value, and all return
> values are values, not pointers. I am wondering if there is an issue
> with the FFI that getting a struct as a return value is causing some
> issues, or passing a cstruct by value. I can think of no other reason
> that this could be happening.
> For example, I have the simple definition in Racket:
> (define cpv
>   (get-ffi-obj "_cpv" chipmunk (_fun _cpFloat _cpFloat -> _cpVect)))
> where chipmunk is a binding to a valid ffi-lib. This corresponds to
> the C function:
> static inline cpVect cpv(const cpFloat x, const cpFloat y)
> {
>         cpVect v = {x, y};
>         return v;
> }
> Calling cpv in Racket at any point will immediately cause a
> segmentation fault. Is my theory about why this is happening correct?
> Or is there something else going on that I am unaware of? I realize
> this is a small function that could easily be re-defined in Racket
> (the current FFI bindings to Chipmunk do this, actually, possibly
> because the developer ran into the same issue I am), but it seems
> important to know why this is happening so as to avoid it in the
> future either with this FFI binding, or any others I might put
> together.
> ____________________
>  Racket Users list:
>  http://lists.racket-lang.org/users

Jens Axel Søgaard

Posted on the users mailing list.