From: Rolando Abarca Date: 2009-05-07T22:21:37+09:00 Subject: Re: storing c pointers in ruby hash On May 7, 2009, at 7:15 AM, Alex Fenton wrote: > Rolando Abarca wrote: > >>> I'm been banging my head on the keyboard the whole day trying to >>> track a bug. > > You probably should post more information about what happens when > the bug hits: eg is it a rb_bug, and if so, with what message? Can > you provide a gdb backtrace of the C call stack? Here's the backtrack when trying to use the Data_Get_Struct() macro on the object back from the hash table: #0 0x000a546c in st_lookup (table=0xdaa29, key=9864, value=0xbfffe28c) at /Users/rolando/Documents/GFF/ShinyCocos/ruby/st.c: 289 #1 0x0010475e in search_method (klass=92302960, id=9864, klassp=0x0) at vm_method.c:229 #2 0x001047a8 in rb_get_method_body (klass=92302960, id=9864, idp=0xbfffe334) at vm_method.c:256 #3 0x00106ff9 in rb_call0 (klass=92302960, recv=92302800, mid=9864, argc=0, argv=0x0, scope=1, self=6) at vm_eval.c:205 #4 0x00106ea7 in rb_call (klass=92302960, recv=92302800, mid=9864, argc=0, argv=0x0, scope=1) at vm_eval.c:255 #5 0x001072cf in rb_funcall (recv=92302800, mid=9864, n=0) at vm_eval.c:427 #6 0x000d10e2 in -[CocosNode(SC_Extension) rb_on_enter] (self=0x5778540, _cmd=0x1a75dc) at /Users/rolando/Documents/GFF/ ShinyCocos/Integration/SC_CocosNode.m:72 #7 0x00174a11 in -[CocosNode onEnter] (self=0x5778330, _cmd=0x19ca9f) at /Users/rolando/Documents/GFF/ShinyCocos/cocos2d-iphone/cocos2d/ CocosNode.m:529 #8 0x000d10ac in -[CocosNode(SC_Extension) rb_on_enter] (self=0x5778330, _cmd=0x1a75dc) at /Users/rolando/Documents/GFF/ ShinyCocos/Integration/SC_CocosNode.m:69 #9 0x00174a11 in -[CocosNode onEnter] (self=0x5775e90, _cmd=0x19ca9f) at /Users/rolando/Documents/GFF/ShinyCocos/cocos2d-iphone/cocos2d/ CocosNode.m:529 #10 0x000d10ac in -[CocosNode(SC_Extension) rb_on_enter] (self=0x5775e90, _cmd=0x1a75dc) at /Users/rolando/Documents/GFF/ ShinyCocos/Integration/SC_CocosNode.m:69 #11 0x00174a11 in -[CocosNode onEnter] (self=0x5775e30, _cmd=0x19ca9f) at /Users/rolando/Documents/GFF/ShinyCocos/cocos2d-iphone/cocos2d/ CocosNode.m:529 #12 0x000d10ac in -[CocosNode(SC_Extension) rb_on_enter] (self=0x5775e30, _cmd=0x1a75dc) at /Users/rolando/Documents/GFF/ ShinyCocos/Integration/SC_CocosNode.m:69 #13 0x00179386 in -[Director setNextScene] (self=0x1070fd0, _cmd=0x1a7882) at /Users/rolando/Documents/GFF/ShinyCocos/cocos2d- iphone/cocos2d/Director.m:649 #14 0x00177a13 in -[Director mainLoop] (self=0x1070fd0, _cmd=0x1a76ff) at /Users/rolando/Documents/GFF/ShinyCocos/cocos2d-iphone/cocos2d/ Director.m:185 #15 0x94505e23 in __NSFireTimer () #16 0x9213cb25 in CFRunLoopRunSpecific () #17 0x9213ccd8 in CFRunLoopRunInMode () #18 0x31566600 in GSEventRunModal () #19 0x315666c5 in GSEventRun () #20 0x30a4eca0 in -[UIApplication _run] () #21 0x30a5a09c in UIApplicationMain () #22 0x0000200a in main (argc=1, argv=0xbfffeee4) at /Users/rolando/ Documents/GFF/ShinyCocos/_DC/main.m:14 > The code looks ok from a casual look, though I'm not sure INT2FIX is > the right conversion macro to use. SWIG does this to create a > conversion macro (SWIG2NUM) for making Ruby hash keys from pointers. > > > /* Ruby 1.8 actually assumes the first case. */ > #if SIZEOF_VOIDP == SIZEOF_LONG > # define SWIG2NUM(v) LONG2NUM((unsigned long)v) > # define NUM2SWIG(x) (unsigned long)NUM2LONG(x) > #elif SIZEOF_VOIDP == SIZEOF_LONG_LONG > # define SWIG2NUM(v) LL2NUM((unsigned long long)v) > # define NUM2SWIG(x) (unsigned long long)NUM2LL(x) > #else > # error sizeof(void*) is not the same as long or long long > #endif I thought about this. I tried using (ruby) string keys just to make sure it wasn't that sort of problem. Same issue. I even went further and removed the hash table, using an instance variable in the objc class that will be linked to a ruby class (I wanted to avoid this). It crashed in the same way. > If above doesn't help, what version of 1.8 were you using > previously? If < 1.8.7 then you might see if the bug is "object > allocation during garbage collection". The size of pointers on Mac > OS X mean that when they are converted to ruby Numerics, they may be > BigNums. These are not immediate objects and involve allocation; if > you happen to do this during GC it's a mistake. Ruby 1.8.6 and > earlier were indulgent to this failing, but 1.8.7 and 1.9.1 are not. It was 1.8.8: the stable snapshot that's on the ruby page, which I mistakenly confused with a stable snapshot of the 1.9.1 series, I think that link is a bit outdated. > You could test this by placing GC.disable at the very start of your > script and seeing if the crash still happens. I'll try that. > Do you have an alternate hash map implementation available, eg from > ObjC standard libraries? Can you use this instead to create a > straight pointer->VALUE map? I would try this as using Ruby Hash > adds unnecessary complexity involved with converting the pointer > keys to VALUE, and GC. I'll try NSDictionary, but as I got the same error using the raw pointer... I'll give it a shot though. > Several of the things you appear to be trying to do (have a > persistent ObjC -> Ruby object link; forward method calls from ObjC > to Ruby) are similar to what SWIG provides for C++ and you might > find it useful to look at the implementation of "object tracking" > and "directors"/"cross-language polymorphism" there. > > The former uses a hash, the latter uses a C++ class which multiply > inherits from the wrapped C++ class and a simple C++ class called > "Director" which has the VALUE as member, and forwards method calls > to rb_funcall on that VALUE. thanks! I'll take a look at that code. > hth > alex regards, -- Rolando Abarca M.