[racket] FFI Pointing to racket objects

16 views
Skip to first unread message

Sam Vervaeck

unread,
Mar 2, 2013, 10:35:58 AM3/2/13
to us...@racket-lang.org

Hi,

 

I am forking an FFI library for physics simulation on Github (https://github.com/samvv/Rhipmunk-Physics) but I got stuck with storing racket objects in the library’s native structs. From the library’s website: http://chipmunk-physics.net/release/Chipmunk-6.x/Chipmunk-6.1.2-API-Reference/group__cp_body.html. Here’s the part of the code that needs to be changed:

                                                                                                

(define _cpDataPointer _racket)

(define-cstruct _cpBody

    …

    [data _cpDataPointer] ; user-defined data, like a game object

    …)

 

In the following test everything seems to work as expected:

 

(define body1 (cpBodyNew 1.0 1.0))

(set-cpBody-data! body1 "This is a test")

(display (cpBody-data body1))

> “This is a test”

(set-cpBody-data! body1 (cons 1 2))

(display (cpBody-data body1))

> (1 . 2)

 

However, when I run the following code:

 

(collect-garbage)

(display (cpBody-data body1))

 

Something goes wrong internally. Sometimes DrRacket crashes, sometimes it returns values like #<bad-value>. I have looked into (malloc-immobile-cell v) and (free-immobile-cell cptr) but I am not sure that fiddling with the memory is such a good idea. Could you please give me any guidelines or point me to a procedure I can use to provide this functionality?

 

Thanks,

 

Sam

Jay McCarthy

unread,
Mar 4, 2013, 8:35:03 AM3/4/13
to Sam Vervaeck, users
I wrote an FFI for Chipmunk once:

https://github.com/jeapostrophe/chipmunk/blob/master/chipmunk-ffi.ss

I used _pointer rather than _racket for my body data.

My understanding is that in your version, the Racket object is only
available via the Chipmunk/C data structure, which the GC views as
opaque, so it is collected. If you want to put Racket things in C
objects, you'll have to make sure they are retained on the Racket
side, by (for example), also storing them in a hash table and
monitoring access to the C objects.

Jay

> ____________________
> Racket Users list:
> http://lists.racket-lang.org/users
>

--
Jay McCarthy <j...@cs.byu.edu>
Assistant Professor / Brigham Young University
http://faculty.cs.byu.edu/~jay

"The glory of God is Intelligence" - D&C 93

____________________
Racket Users list:
http://lists.racket-lang.org/users

Matthew Flatt

unread,
Mar 4, 2013, 8:59:10 AM3/4/13
to Jay McCarthy, users, Sam Vervaeck
At Mon, 4 Mar 2013 06:35:03 -0700, Jay McCarthy wrote:
> My understanding is that in your version, the Racket object is only
> available via the Chipmunk/C data structure, which the GC views as
> opaque, so it is collected. If you want to put Racket things in C
> objects, you'll have to make sure they are retained on the Racket
> side, by (for example), also storing them in a hash table and
> monitoring access to the C objects.

Retaining a reference to the value from elsewhere won't be enough,
usually. The GC might move the value, in which case the C data
structure's field will point to the wrong place.

> On Sat, Mar 2, 2013 at 8:35 AM, Sam Vervaeck <vervae...@skynet.be> wrote:
> > I have looked into (malloc-immobile-cell
> > v) and (free-immobile-cell cptr) but I am not sure that fiddling with the
> > memory is such a good idea. Could you please give me any guidelines or point
> > me to a procedure I can use to provide this functionality?

The `malloc-immobile-cell' and `free-immobile-cell' functions really
are the way to go.

Sam Vervaeck

unread,
Mar 4, 2013, 11:12:05 AM3/4/13
to us...@racket-lang.org
Hi Jay,

I know, I actually used your code and a fork of it on github as a starting point (https://github.com/Freezerburn/Rhipmunk-Physics). It really helped a lot! I have added your name to the authors list. If you have an issue with that I can remove it of course.

I'm going to use Matthew's solution just to make sure no pointers get messed up.

Sam

-----Oorspronkelijk bericht-----
Van: Jay McCarthy [mailto:jay.mc...@gmail.com]
Verzonden: maandag 4 maart 2013 14:35
Aan: Sam Vervaeck
CC: users
Onderwerp: Re: [racket] FFI Pointing to racket objects

Sam Vervaeck

unread,
Mar 4, 2013, 12:06:10 PM3/4/13
to Matthew Flatt, Jay McCarthy, users
Thanks Mattew, I suspected moving the value was causing the issue.

Just one more question: when implementing malloc-immobile-cell and free-immobile-cell, how do you check if a pointer has not yet been set? Doing things like:

(if (cpBody-data body1)
"I have some data"
"I have nothing")

Always shows "I have nothing". 'ptr-equal?' also doesn't seem to work. Is there some procedure like 'ptr-set?' I'm looking over in the manual? Or do I just set something in the beginning like (malloc-immobile-cell 'no-val-yet)?

-----Oorspronkelijk bericht-----
Van: Matthew Flatt [mailto:mfl...@cs.utah.edu]
Verzonden: maandag 4 maart 2013 14:59
Aan: Jay McCarthy
CC: Sam Vervaeck; users
Onderwerp: Re: [racket] FFI Pointing to racket objects

Matthew Flatt

unread,
Mar 4, 2013, 12:26:26 PM3/4/13
to Sam Vervaeck, users
At Mon, 4 Mar 2013 18:06:10 +0100, "Sam Vervaeck" wrote:
> Just one more question: when implementing malloc-immobile-cell and
> free-immobile-cell, how do you check if a pointer has not yet been set? Doing
> things like:
>
> (if (cpBody-data body1)
> "I have some data"
> "I have nothing")
>
> Always shows "I have nothing".

I expected that the `data' field would have an immutable-cell value ---
which might contain #f but not be #f itself --- so I expected "I have
some data" always.

You should use `ptr-ref' and `pre-set!' to get or change the value in
an immobile cell. Here's an example transcript:

> (define-cstruct _cpBody ([data _racket]))
> (define b (make-cpBody (malloc-immobile-cell #f)))
> (cpBody-data b)
#<cpointer>
> (ptr-ref (cpBody-data b) _racket)
#f
> (ptr-set! (cpBody-data b) _racket 'something)
> (collect-garbage)
> (ptr-ref (cpBody-data b) _racket)
'something

Sam Vervaeck

unread,
Mar 5, 2013, 5:57:24 PM3/5/13
to Matthew Flatt, users
The data is user-defined so that's why it might change. There's a small bug in the second part of your example but I get the idea. Using ptr-set! directly gives me the same problem with the garbage collector, probably because it isn't pointing to an immobile cell anymore. Wrapping it up with a 'malloc-immobile-cell' makes everything work. Here's a full example if anyone's interested:

(define (cpBodyGetData cpBody) ; get the contents of the old cell
(ptr-ref (cpBody-data cpBody))

(define (cpBodySetData cpBody val) ; change it to a new cell
(free-immobile-cell (cpBody-data cpBody))
(set-cpBody-data! cpBody (malloc-immobile-cell val)))

This of course requires that an initial (empty) cell is set when make-cpBody is called, since no predicate is available to test the data pointer.

Thanks again,

Sam
-----Oorspronkelijk bericht-----
Van: Matthew Flatt [mailto:mfl...@cs.utah.edu]
Verzonden: maandag 4 maart 2013 18:26
Aan: Sam Vervaeck
CC: 'users'
Onderwerp: Re: [racket] FFI Pointing to racket objects

Reply all
Reply to author
Forward
0 new messages