For dealing with Clr-backed objects such as Exception should we just create special cases in the Marshal to dump and load them? Is there any way I can find out what other ruby objects are actually CLR objects other than Exception types and the basic int, double, float types?
My experiments with extending the marshal to dump CLR types were interesting. I can dump and load pure CLR types such as System::DateTime, and in theory it should also work seamlessly for CLR classes that have been "extended" by ruby. The code is quite simple, it just extends the marshaller and add a few extra nonstandard type codes for CLR primitive types such as System::Int64 that can't be dealt with by the ruby marshaller. You wouldn't be able to unmarshal a Pure or extended CLR object from CRuby as it wouldn't understand these extra type codes but that doesn't make any sense anyway. Because the marshal extensions preserve all the CLR information for exceptions, an IronRuby Exception won't be able to be loaded by CRuby, so to keep compatibility there would have to be special cases for Exceptions (and any other builtin CLR objects that masquerade as ruby objects) whether the ISerializable code stays or goes. Are there any unit tests or specs for the marshalling? There doesn't seem to be any mention of it in IronRuby.Tests.csproj, but I haven't looked through all the rubyspec stuff yet. From: Tomas Matousek <tomas.matou...@microsoft.com> To: "ironruby-core@rubyforge.org" <ironruby-core@rubyforge.org> Date: 26/10/2011 03:42 p.m. Subject: Re: [Ironruby-core] IronRuby's Marshal.dump doesn't work with CLR types, or ruby types backed by a CLR type Sent by: ironruby-core-boun...@rubyforge.org I think we should NOT serialize non-Ruby types for now. The implementation isn?t quite working so I?d prefer we delete all code that deals with ISerializable, clean up the marshaller and if .NET serialization is needed in future implement it fully and correctly. Marshal.dump has to output exactly the same data as CRuby implementation (for Ruby objects). Otherwise you won?t be able to read data serialized by CRuby in IronRuby and vice versa. Tomas From: ironruby-core-boun...@rubyforge.org [ mailto:ironruby-core-boun...@rubyforge.org] On Behalf Of Orion Edwards Sent: Tuesday, October 25, 2011 6:22 PM To: ironruby-core@rubyforge.org Subject: [Ironruby-core] IronRuby's Marshal.dump doesn't work with CLR types, or ruby types backed by a CLR type Backstory: I'm trying to use DRb for some in-house utility code. DRb itself seems to work fine, but I found that when I misspelled a method name, instead of reporting back a NoMethodError, the IronRuby process crashed immediately to the console. This is using a relatively recent build of IronRuby from Github Steps to repro: e = RuntimeError.new 'xyz' dumped = Marshal.dump e e2 = Marshal.load dumped I would expect e2 to be equivalent to e, but instead the process crashes with this exception mscorlib:0:in `_InvokeConstructor': Exception has been thrown by the target of an invocation. (System::Reflection::TargetInvocationException) from mscorlib:0:in `InvokeConstructor' from mscorlib:0:in `Invoke' from (ir):1:in `load' from (ir):1 Note: This also happens with any CLR type eg System::DateTime. I looked through IronRuby's marshalling code, and it appears that the behaviour of Marshal.dump and Marshal.load don't align properly. Marshal.dump is it's own self-contained set of code which essentially writes data to a BinaryStream. For ruby types, it ends up writing a series of values in a format that looks a lot like what I remember CRuby's marshal writing. For CLR types, this just writes the Type name and no instance data (clr objects don't have ruby instance variables after all) Marshal.load does 2 things: 1. Reads any ruby instance variables out into an Attributes dictionary 2. Uses reflection to find any non-public Constructor(SerializationInfo, StreamingContext) and invoke it. For ruby types, this finds the protected RubyClass(SerializationInfo, StreamingContext) ctor, which calls RubyOps.DeserializeObject, which in turn reads the attributes dictionary and it's all fine. For CLR types, this finds whatever constructor might exist for the CLR object, which does whatever it does for that type. Unfortunately because the data that is getting passed into the CLR deserialization constructor came from Marshal.dump which has no knowledge whatsoever of CLR serialization, the whole thing crashes. I'm no expert on CLR serialization, so I'd really appreciate some comments on this, as I'm not sure what to do here. As far as I can guess however, I can see two solutions: 1. Implement Marshal.dump on top of the CLR serialization code so it matches Marshal.load and should therefore be able to handle CLR types too. 2. Don't allow marshalling of CLR types, and put some special-case code into any Ruby types that are backed by CLR types (such as Exception) so these at least can be serialized? I'm going to have a crack at #1, but I'm not sure how successful this is. Again, any feedback would be greatly appreciated. Thanks, Orion_______________________________________________ Ironruby-core mailing list Ironruby-core@rubyforge.org http://rubyforge.org/mailman/listinfo/ironruby-core
_______________________________________________ Ironruby-core mailing list Ironruby-core@rubyforge.org http://rubyforge.org/mailman/listinfo/ironruby-core