Re: [racket-users] Fun with Physics: Racket FFI Question (Bug?)

2018-09-18 Thread Stephen Foster
Thanks, this is super helpful. :)

On Monday, September 17, 2018 at 9:58:06 AM UTC-7, Matthew Flatt wrote:
>
> At Mon, 17 Sep 2018 09:34:46 -0700 (PDT), Stephen Foster wrote: 
> > But when I have two bodies that share the same velocity_func, I get a 
> > segfault: 
>
> The problem is that a callback is retained (by default) as long as the 
> function that it wraps is retained, but only a single callback is 
> retained for a given function. So, creating a second callback loses the 
> link between the function and the first callback, and the first 
> callback can be is reclaimed by the GC. 
>
> This is often a difficult problem to solve. 
>
> > *Things that didn't work* 
> > 
> > 1) Wrapping the function f in separate lambdas still gives a segfault: 
> > 
> > (set-cpBody-velocity_func! (chipmunk-body body1) 
> >(lambda(b g d dt) 
> >  (f b d g dt))) 
> > 
> > (set-cpBody-velocity_func! (chipmunk-body body2) 
> >(lambda(b g d dt) 
> >  (f b d g dt))) 
>
> This change makes things slightly worse, because nothing retains either 
> of those individual lambdas. 
>
> > 2) Storing a reference to the function f in a stab-in-the-dark attempt 
> to 
> > "trick the system" or "prevent some kind of mysterious garbage 
> collection" 
> > still segfaults: 
> > 
> > (define probably-silly 
> >   (list 
> > (lambda(b g d dt) 
> >   (f b d g dt)) 
> > (lambda(b g d dt) 
> >   (f b d g dt 
> > 
> > (set-cpBody-velocity_func! (chipmunk-body body1) 
> >(list-ref probably-silly 0)) 
> > 
> > (set-cpBody-velocity_func! (chipmunk-body body2) 
> >(list-ref probably-silly 1)) 
>
> Honestly, I'm not clear on why this fails. The `probably-silly` list 
> should be retained via the module's namespace, and so both of those 
> `lambda`s should be preserved, and so both callbacks should be 
> preserved. I'm stumped. 
>
>
> > 3) Storing the function f in two separate variables also segfaults: 
> > 
> > (define (f body gravity damping dt) 
> >   (ffi:cpointer-push-tag! body 'cpBody) 
> >   (cpBodySetVelocity body (cpv 0 -10)) 
> > 
> >   ffi:_void) 
> > 
> > (define f2 f) 
>
> This does nothing, since `f` and `f2` refer to the same value. 
>
>
> > *Things that do work but feel dumb* 
> > 
> > 1) Explicitly duplicating the function verbatim: 
> > 
> > (define (f body gravity damping dt) 
> >   (ffi:cpointer-push-tag! body 'cpBody) 
> >   (cpBodySetVelocity body (cpv 0 -10)) 
> > 
> >   ffi:_void) 
> > 
> > (define (f2 body gravity damping dt) 
> >   (ffi:cpointer-push-tag! body 'cpBody) 
> >   (cpBodySetVelocity body (cpv 0 -10)) 
> > 
> >   ffi:_void) 
> > 
> > (set-cpBody-velocity_func! (chipmunk-body body1) 
> >f) 
> > 
> > (set-cpBody-velocity_func! (chipmunk-body body2) 
> >f2) 
>
> This works because each callbacks is associated to a separate function, 
> and the separate functions are retained through the module's namespace. 
>
> > 2) Duplicating the function with a macro lets me generalize the above 
> > workaround for more than two bodies, but it still feels gross. 
>
> Yes. 
>
>
> > If someone has an explanation or a better workaround, that would be 
> great.   
>
> Use `#:keep` in the `_fun` for the velocity callback. 
>
> To tie the callback's lifetime to the enclosing record, you can 
> probably use a weak hashtable mapping `cpBody` pointers to callbacks: 
>
>   (define callbacks (make-weak-hasheq)) 
>   (define current-cpBody (make-parameter #f)) 
>
>   (define _cpBodyVelocityFunc 
>  (_fun #:keep (lambda (cb) (hash-set! callbacks (current-cpBody) cb)) 
>_pointer _cpVect _cpFloat _cpFloat -> _void)) 
>   
> where `current-cpBody` is a way of communicating the record where the 
> pointer is being stored: 
>
>   (let ([body (chipmunk-body body1)]) 
> (parameterize ([current-cpBody body])) 
>   (set-cpBody-velocity_func! body 
>   f)) 
>
> Beware that `callbacks` ties the callback to a cpointer record, not to 
> the actual pointer value. Since `chipmunk-body` returns the same 
> Cpointer every time for a given `chipmunk` Racket structure, I think 
> that's ok --- but it won't be ok if you get the same body pointer from 
> Chipmunk (via the FFI) multiple times. 
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Fun with Physics: Racket FFI Question (Bug?)

2018-09-17 Thread Matthew Flatt
At Mon, 17 Sep 2018 09:34:46 -0700 (PDT), Stephen Foster wrote:
> But when I have two bodies that share the same velocity_func, I get a 
> segfault:

The problem is that a callback is retained (by default) as long as the
function that it wraps is retained, but only a single callback is
retained for a given function. So, creating a second callback loses the
link between the function and the first callback, and the first
callback can be is reclaimed by the GC.

This is often a difficult problem to solve.

> *Things that didn't work*
> 
> 1) Wrapping the function f in separate lambdas still gives a segfault:
> 
> (set-cpBody-velocity_func! (chipmunk-body body1)
>(lambda(b g d dt)
>  (f b d g dt)))
> 
> (set-cpBody-velocity_func! (chipmunk-body body2)
>(lambda(b g d dt)
>  (f b d g dt)))

This change makes things slightly worse, because nothing retains either
of those individual lambdas.

> 2) Storing a reference to the function f in a stab-in-the-dark attempt to 
> "trick the system" or "prevent some kind of mysterious garbage collection" 
> still segfaults:
> 
> (define probably-silly
>   (list
> (lambda(b g d dt)
>   (f b d g dt))
> (lambda(b g d dt)
>   (f b d g dt
> 
> (set-cpBody-velocity_func! (chipmunk-body body1)
>(list-ref probably-silly 0))
> 
> (set-cpBody-velocity_func! (chipmunk-body body2)
>(list-ref probably-silly 1))

Honestly, I'm not clear on why this fails. The `probably-silly` list
should be retained via the module's namespace, and so both of those
`lambda`s should be preserved, and so both callbacks should be
preserved. I'm stumped.


> 3) Storing the function f in two separate variables also segfaults:
> 
> (define (f body gravity damping dt)
>   (ffi:cpointer-push-tag! body 'cpBody)
>   (cpBodySetVelocity body (cpv 0 -10))
> 
>   ffi:_void)
> 
> (define f2 f)

This does nothing, since `f` and `f2` refer to the same value.


> *Things that do work but feel dumb*
> 
> 1) Explicitly duplicating the function verbatim:
> 
> (define (f body gravity damping dt)
>   (ffi:cpointer-push-tag! body 'cpBody)
>   (cpBodySetVelocity body (cpv 0 -10))
> 
>   ffi:_void)
> 
> (define (f2 body gravity damping dt)
>   (ffi:cpointer-push-tag! body 'cpBody)
>   (cpBodySetVelocity body (cpv 0 -10))
> 
>   ffi:_void)
> 
> (set-cpBody-velocity_func! (chipmunk-body body1)
>f)
> 
> (set-cpBody-velocity_func! (chipmunk-body body2)
>f2)

This works because each callbacks is associated to a separate function,
and the separate functions are retained through the module's namespace.

> 2) Duplicating the function with a macro lets me generalize the above 
> workaround for more than two bodies, but it still feels gross.

Yes.


> If someone has an explanation or a better workaround, that would be great.  

Use `#:keep` in the `_fun` for the velocity callback.

To tie the callback's lifetime to the enclosing record, you can
probably use a weak hashtable mapping `cpBody` pointers to callbacks:

  (define callbacks (make-weak-hasheq))
  (define current-cpBody (make-parameter #f))

  (define _cpBodyVelocityFunc
 (_fun #:keep (lambda (cb) (hash-set! callbacks (current-cpBody) cb))
   _pointer _cpVect _cpFloat _cpFloat -> _void))
  
where `current-cpBody` is a way of communicating the record where the
pointer is being stored:

  (let ([body (chipmunk-body body1)])
(parameterize ([current-cpBody body]))
  (set-cpBody-velocity_func! body
  f))

Beware that `callbacks` ties the callback to a cpointer record, not to
the actual pointer value. Since `chipmunk-body` returns the same
Cpointer every time for a given `chipmunk` Racket structure, I think
that's ok --- but it won't be ok if you get the same body pointer from
Chipmunk (via the FFI) multiple times.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[racket-users] Fun with Physics: Racket FFI Question (Bug?)

2018-09-17 Thread Stephen Foster
I'm trying to get the Chipmunk Physics library integrated with Racket.  
I've made some progress (https://www.youtube.com/watch?v=GjvLaP7I0gg), but 
I need to ask for some input on an issue.

The Chipmunk C library provides a primitive called a "cpBody" (i.e. a 
moving thing).  A cpBody struct has a velocity_func pointer which allows 
customization of how the body's velocity is updated during the simulation.

I have noticed odd behavior with these function pointers.  Perhaps this is 
a bug with the FFI?  Perhaps it's perfectly normal and I just don't 
understand something about the FFI?

In any event, when I have one body, this works:

(define body1
  (box 25 5 (cpv 25.0 80.0)
   #:mass 10
   #:meta 'green))

(define (f body gravity damping dt)
  (ffi:cpointer-push-tag! body 'cpBody)
  (cpBodySetVelocity body (cpv 0 -10))

  ffi:_void)

(set-cpBody-velocity_func! (chipmunk-body body1)
   f)


But when I have two bodies that share the same velocity_func, I get a 
segfault:

(define body1
  (box 25 5 (cpv 25.0 80.0)
   #:mass 10
   #:meta 'green))

(define body2
  (box 25 5 (cpv 50.0 80.0)
   #:mass 10
   #:meta 'blue))


(define (f body gravity damping dt)
  (ffi:cpointer-push-tag! body 'cpBody)
  (cpBodySetVelocity body (cpv 0 -10))

  ffi:_void)

(set-cpBody-velocity_func! (chipmunk-body body1)
   f)

(set-cpBody-velocity_func! (chipmunk-body body2)
   f)


I've tried various ways to work around this issue.  But all of them either 
didn't work or feel dumb.


*Things that didn't work*

1) Wrapping the function f in separate lambdas still gives a segfault:

(set-cpBody-velocity_func! (chipmunk-body body1)
   (lambda(b g d dt)
 (f b d g dt)))

(set-cpBody-velocity_func! (chipmunk-body body2)
   (lambda(b g d dt)
 (f b d g dt)))


2) Storing a reference to the function f in a stab-in-the-dark attempt to 
"trick the system" or "prevent some kind of mysterious garbage collection" 
still segfaults:

(define probably-silly
  (list
(lambda(b g d dt)
  (f b d g dt))
(lambda(b g d dt)
  (f b d g dt

(set-cpBody-velocity_func! (chipmunk-body body1)
   (list-ref probably-silly 0))

(set-cpBody-velocity_func! (chipmunk-body body2)
   (list-ref probably-silly 1))

3) Storing the function f in two separate variables also segfaults:

(define (f body gravity damping dt)
  (ffi:cpointer-push-tag! body 'cpBody)
  (cpBodySetVelocity body (cpv 0 -10))

  ffi:_void)

(define f2 f)

(set-cpBody-velocity_func! (chipmunk-body body1)
   f)

(set-cpBody-velocity_func! (chipmunk-body body2)
   f2)



*Things that do work but feel dumb*

1) Explicitly duplicating the function verbatim:

(define (f body gravity damping dt)
  (ffi:cpointer-push-tag! body 'cpBody)
  (cpBodySetVelocity body (cpv 0 -10))

  ffi:_void)

(define (f2 body gravity damping dt)
  (ffi:cpointer-push-tag! body 'cpBody)
  (cpBodySetVelocity body (cpv 0 -10))

  ffi:_void)

(set-cpBody-velocity_func! (chipmunk-body body1)
   f)

(set-cpBody-velocity_func! (chipmunk-body body2)
   f2)

2) Duplicating the function with a macro lets me generalize the above 
workaround for more than two bodies, but it still feels gross.  I know the 
macro could be improved, but that isn't really the point.  The fact that I 
have to know how many  functions to make at compile time is gross.

;The stupid macro
(define-syntax-rule (dumb-duplicate id body)
  (define id
(list
 body
 body
 body
 body
 body)))

(dumb-duplicate fs
(lambda (body gravity damping dt)
  (f body gravity damping dt)))

(set-cpBody-velocity_func! (chipmunk-body body1)
   (list-ref fs 0))

(set-cpBody-velocity_func! (chipmunk-body body2)
   (list-ref fs 1))


That's all I have.  To sum up, sharing the same function pointer across two 
cpBodies seems to segfault to matter what clever tricks I try.  Using 
functions with distinct compile-time source locations does work, but it 
makes me feel icky.  I would prefer to construct the functions I need 
dynamically rather than statically.  In simulations where objects are 
created at runtime, it feels sillier and sillier to have to know beforehand 
how many objects there will be at runtime.

If someone has an explanation or a better workaround, that would be great.  
I'm assuming there's something about the Racket FFI that I haven't learned 
yet.  However, if others are as mystified as I am, I'll assume it's a 
Chipmunk issue, and I'll ask about it over on the Chipmunk forums.  


*Appendix A*

Below is a full program with some rendering, just for context.

It uses this newborn git repo for