Thomas said:
Q1) I am wondering about the rb_gc_register_address/rb_gc_unregister_address
function pairs.
The both take a VALUE pointer rather than a VALUE. Does that mean that to
unregister I have to pass it the exact same VALUE pointer, or will another
VALUE pointer pointing to the same object be equivalent. I'm asking because
I might rb_gc_register_address and rb_gc_unregister_address multiple times
for the same VALUE, but only once with each VALUE pointer.
It uses the address, not the value.
Here's a scenario:
VALUE array = rb_ary_new(); // At some point this array is created
somewhere in ruby
... a little later ...
// I need to pass a reference of the object out of ruby's reach
// so I 'lock' the object with rb_gc_register_address and keep the arrayRef
// pointer with me somewhere safe
VALUE *arrayRef = ALLOC(VALUE);
*arrayRef = array;
rb_gc_register_address(arrayRef)
[...snip...]
Is this the way to do it?
That way would work fine, I think, but it seems a little convoluted.
If your C/C++ object has a VALUE member, you need only register the
address of that just once, and unregister it in the destructor. As long
as your C/C++ object is around, the VALUE is registered and the object
it is tied to will not go away.
Also, if the VALUE you need is just temporary for while you're in a C
call, just use a regular VALUE stack variable; they're protected (see
below) while in-use and cleaned up automatically when you're done with them.
Inversely, if you're trying to tie an C/C++ object/data to a Ruby
object, just use malloc to allocated it and associate it with a Ruby
object with Data_Wrap_Struct and provide a free function (use the normal
free/malloc routines).
Q2) Another thing that I am wondering about. Can the GC be invoked in the
middle of my C code or does that only happen when control is in the "guts of
ruby". What prevents the VALUEs I have on the stack from being GC'ed in that
case?
The GC can be invoked whenever you call any Ruby function. The Ruby GC
scans the stack for VALUE variables and "marks" any it finds which point
to valid objects. So long as the current stack pointer is
deeper/further into the stack than your VALUE variable, it is protected.
When your C/C++ function returns, it is eligible for collection and
will be left unmarked during the next GC sweep.
One gotcha I learned about this is, the object must really be on the
stack. Compilers these days all optimize, so to be sure your variable
actually lives on the stack and not in a register somewhere, all VALUEs
that you want marked as in-use, you must declare it as volatile, i.e.:
volatile VALUE tempArray;
Sean O'Dell