Lisp HUG Maillist Archive

Strange behavior with the FLI

Hello,

I am interfacing LispWorks 64 bits on Mac OS X to C functions returning a very simple structure:

struct _vector {
  float x;
  float y;
  float z;
}
typedef struct _vector vector;

vector direction();
vector position();
vector velocity();


In LispWorks, when I call this:

(fli:with-dynamic-foreign-objects ((direction vector)
                                   (position vector)
                                   (velocity vector))
      (direction :result-pointer direction)
      (position :result-pointer position)
      (velocity :result-pointer velocity)
      (list :direction (dump-vector direction))
            :position  (dump-vector position))
            :velocity  (dump-vector velocity))))

Where:

(defun dump-vector (vector)
  (list (fli:foreign-slot-values vector 'x)
        (fli:foreign-slot-values vector 'y)
        (fli:foreign-slot-values vector 'z)))

The result I get is something like:

(DIRECTION (0.0  yyy1 zzz1)
 POSITION  (0.0  yyy2 zzz2)
 VELOCITY  (xxx3 yyy3 zzz3))

The value 0.0 for the component X of direction and position is unexpected, I know the C library does not return 0.0.  More surprising, velocity has all its 3 components with non 0.0 values.


Now, if I change the order to something else:

(fli:with-dynamic-foreign-objects ((direction vector)
                                   (position vector)
                                   (velocity vector))
      ;;
      ;; I have swapped the first two lines below...
      ;;
      (position :result-pointer position)
      (direction :result-pointer direction)
      (velocity :result-pointer velocity)
      (list :direction (dump-vector direction))
            :position  (dump-vector position))
            :velocity  (dump-vector velocity))))


I get a slightly better result, a component is still 0.0 though ...

(DIRECTION (xxx1 yyy1 zzz1)
 POSITION  (0.0 yyy2 zzz2)
 VELOCITY  (xxx3 yyy3 zzz3))


Now I have found that this outputs the correct results:

(fli:with-dynamic-foreign-objects ((direction vector)
                                   (position vector)
                                   (velocity vector))
      ;;
      ;; the three following lines were swapped...
      ;;
      (velocity :result-pointer velocity)
      (position :result-pointer position)
      (direction :result-pointer direction)
      (list :direction (dump-vector direction))
            :position  (dump-vector position))
            :velocity  (dump-vector velocity))))


I'm unsure of this but it looks like my foreign objects which size is 12 bytes are aligned on a 16 bytes boundary, but somehow accessed contiguously.  Can an enlightening soul please help me understand why?


All the best,
Cam



_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html


Re: Strange behavior with the FLI

You haven't shown the C code, but, has this got anything to do with the 
fact that structs are passed and returned by value in C? (Arrays are 
passed by reference, but not structs).

If this were Windows, I'd also tell you to look at the calling 
convention declaration (pascal vs. c).

pt

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html


Re: Strange behavior with the FLI

Hello,


Some new finding about this issue:

- the same code with LispWorks Professional 32 bits on Mac OS X works as expected.
- I am almost sure that each call to the foreign functions [see 1] overwrite the stack next where the other dynamic foreign objects buffers are allocated.  This is why a different order of the foreign function calls gives different results.
- I have tried with GCC instead of clang without success.
- I have not tried to return the structure by passing a pointer to the foreign functions (instead of returning the struct by value as it is right now), but I have good faith that it would work, yet I would really love to understand why my foreign allocations are overwritten.


Best,
Cam


[1]
(fli:with-dynamic-foreign-objects ((direction vector)
                                  (position vector)
                                  (velocity vector))
     ;; each call here overwrite the stack by 4 more bytes
     (direction :result-pointer direction)
     (position :result-pointer position)
     (velocity :result-pointer velocity)
     (list :direction (dump-vector direction))
           :position  (dump-vector position))
           :velocity  (dump-vector velocity))))


On 23 janv. 2013, at 01:05, Camille Troillard <camille@osculator.net> wrote:

> Hello,
> 
> I am interfacing LispWorks 64 bits on Mac OS X to C functions returning a very simple structure:
> 
> struct _vector {
>  float x;
>  float y;
>  float z;
> }
> typedef struct _vector vector;
> 
> vector direction();
> vector position();
> vector velocity();
> 
> 
> In LispWorks, when I call this:
> 
> (fli:with-dynamic-foreign-objects ((direction vector)
>                                   (position vector)
>                                   (velocity vector))
>      (direction :result-pointer direction)
>      (position :result-pointer position)
>      (velocity :result-pointer velocity)
>      (list :direction (dump-vector direction))
>            :position  (dump-vector position))
>            :velocity  (dump-vector velocity))))
> 
> Where:
> 
> (defun dump-vector (vector)
>  (list (fli:foreign-slot-values vector 'x)
>        (fli:foreign-slot-values vector 'y)
>        (fli:foreign-slot-values vector 'z)))
> 
> The result I get is something like:
> 
> (DIRECTION (0.0  yyy1 zzz1)
> POSITION  (0.0  yyy2 zzz2)
> VELOCITY  (xxx3 yyy3 zzz3))
> 
> The value 0.0 for the component X of direction and position is unexpected, I know the C library does not return 0.0.  More surprising, velocity has all its 3 components with non 0.0 values.
> 
> 
> Now, if I change the order to something else:
> 
> (fli:with-dynamic-foreign-objects ((direction vector)
>                                   (position vector)
>                                   (velocity vector))
>      ;;
>      ;; I have swapped the first two lines below...
>      ;;
>      (position :result-pointer position)
>      (direction :result-pointer direction)
>      (velocity :result-pointer velocity)
>      (list :direction (dump-vector direction))
>            :position  (dump-vector position))
>            :velocity  (dump-vector velocity))))
> 
> 
> I get a slightly better result, a component is still 0.0 though ...
> 
> (DIRECTION (xxx1 yyy1 zzz1)
> POSITION  (0.0 yyy2 zzz2)
> VELOCITY  (xxx3 yyy3 zzz3))
> 
> 
> Now I have found that this outputs the correct results:
> 
> (fli:with-dynamic-foreign-objects ((direction vector)
>                                   (position vector)
>                                   (velocity vector))
>      ;;
>      ;; the three following lines were swapped...
>      ;;
>      (velocity :result-pointer velocity)
>      (position :result-pointer position)
>      (direction :result-pointer direction)
>      (list :direction (dump-vector direction))
>            :position  (dump-vector position))
>            :velocity  (dump-vector velocity))))
> 
> 
> I'm unsure of this but it looks like my foreign objects which size is 12 bytes are aligned on a 16 bytes boundary, but somehow accessed contiguously.  Can an enlightening soul please help me understand why?
> 
> 
> All the best,
> Cam
> 
> 
> 
> _______________________________________________
> Lisp Hug - the mailing list for LispWorks users
> lisp-hug@lispworks.com
> http://www.lispworks.com/support/lisp-hug.html
> 


_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html


Updated at: 2020-12-10 08:36 UTC