From: Charles Mills Date: 2004-07-31T00:19:16+09:00 Subject: Re: C ext: GC claiming objects early On Jul 30, 2004, at 7:06 AM, Tilman Sauerbeck wrote: > ts [2004-07-30 15:43]: >>>>>>> "T" == Tilman Sauerbeck writes: >> >> T> "some_meth" will instantiate a new "Result" object. Using this >> Result >> T> object, the caller can wait for the function to succeed, he can >> register >> T> callbacks etc. >> >> Well it's best if you post the *real* C code : it's easy to >> understand >> than this strange language, called english. > > Heh :) > > Here's the code for the method "some_meth", let's just call it > "playback_playtime" now ;D > > static VALUE c_playback_playtime (VALUE self) > { > xmmsc_result_t *res; > > /* this just wraps Data_Get_Struct */ > GET_OBJ (self, xmmsc_connection_t *, xmms); > > res = xmmsc_playback_playtime (*xmms); > > /* now create a new Result object from the C struct */ > return TO_XMMS_CLIENT_RESULT (self, res); > } > > VALUE TO_XMMS_CLIENT_RESULT (VALUE parent, xmmsc_result_t *res) > { > VALUE self; > RbResult *rbres = NULL; > > if (!res) > return Qnil; > > self = Data_Make_Struct (cResult, RbResult, c_mark, c_free, rbres); > rbres->real = res; > rbres->parent = parent; > rbres->callback = Qnil; You should show us c_mark and c_free In extreme situations the above code it dangerous, here is a safer version: VALUE self; RbResult *rbres; if (!res) return Qnil; rbres = ALLOC(RbRecsult); rbres->real = res; rbres->parent = parent; rbres->callback = Qnil; self = Data_Wrap_Struct (cResult, c_mark, c_free, rbres); > > rb_obj_call_init (rbres->self, 0, NULL); > > return self; Where did rbres->self come from? Doesn't look like you initialized it. You need to pass a valid Ruby object to rb_obj_call_init(), perhaps you intended: return rb_obj_call_init(self, 0, 0); /* returns self */ > } > > 'parent' is the Ruby object that the object marks in c_mark > > This is the "notifier" method of the Result object and the callback > used > to call the given block: > > static void on_signal (xmmsc_result_t *res2, void *data) > { > /* call the block and create a new Result object from res2, too */ > rb_funcall ((VALUE) data, rb_intern ("call"), 1, > TO_XMMS_CLIENT_RESULT (Qnil, res2)); > } > > static VALUE c_notifier_set (VALUE self) > { > GET_OBJ (self, RbResult, res); > > if (!rb_block_given_p ()) > return Qnil; > > res->callback = rb_block_proc (); > xmmsc_result_notifier_set (res->real, on_signal, (void *) > res->callback); This could be your problem. We encountered a similar problem last night with the Rendezvous Ruby wrappers. rb_block_proc() creates a ruby object. your registering on_signal as your event handler, and it looks like what ever library you are using (you should supply more code here) will the pass the void* to the call back for you. You need to show c_mark() so it is clear that your marking everything. -Charlie > > return Qnil; > } > > It's pretty straight-forward and the comment should explain it all :) > > Thanks for any hints. > > -- > Regards, > Tilman >