From: Joel VanderWerf Date: 2002-02-19T09:41:22+09:00 Subject: Re: dump/load a class that has C and Ruby data David Alan Black wrote: > > Hello -- > > On Sun, 17 Feb 2002, Joel VanderWerf wrote: > > > > > I have some classes whose instances have C data as well as Ruby attrs. > > If I Marshal::dump them, I lose the C part. So I have to define _dump in > > my classes. Well, it's not so hard to pack my C data up into a string. I > > can even put this string in a Ruby attribute. But then how do I dump the > > Ruby part? I don't really want to reimplement all the work in > > Marshal::dump just for my classes. I wish there was a way to call > > Marshal::dump with an argument that said "ignore the _dump". Then my > > _dump could first pack the C data into an attr, and then call dump in > > this way, and I'd be all set. Shouldn't Marshal::dump be more easy to > > reuse? > > > > Anybody know a way to do this? > > You could put a hook into Marshal::dump, and flag the objects you > wanted to receive special treatment. Adapting an idea from Dave > Thomas, in the recent respond_to? thread: Well, it turns out that Marshal.dump will raise a TypeError if the object is a T_DATA rather than a T_OBJECT or something else it knows about. So dumping your C data and then calling old_dump on your object doesn't work. I had hoped dump would go ahead and dump the Ruby attrs, ignoring the C data. I guess it's better to noisily fail than to quietly do a half-assed job. Back to square one: how do I dump an object that has Ruby attrs as well as C data? 1. Copy the serialization functions (all static, wouldn't you know) from marshal.c, modify them slightly to do what I want, and call them from my _dump? (Too much work, vulnerable to changes in ruby.) 2. Temporarily reset the type of my object to T_OBJECT just to get Marshal.dump to handle the Ruby data. (Nasty hack, won't work for loading.) 3. Follow the suggestion pointed out in ruby-talk:34046: In my _dump, create a dummy object (an array will do) that refers to all of my data, both Ruby and C, and call Marshal.dump on that. But loading is not so easy. You load the array, which tells you what class the object should be, as well as the values of the attrs. Then you have to rb_obj_alloc an instance (you can't call new), and repeat the work that goes on in r_regist and r_ivar. Again, this introduces a dependency on Ruby source code. That's probably the best solution, but it's frustrating that it is so awkward. It would have been so nice just to call super from within my _dump method.... -- Joel VanderWerf California PATH, UC Berkeley mailto:vjoel@path.berkeley.edu Ph. (510) 231-9446 http://www.path.berkeley.edu FAX (510) 231-9512