Hi @stevebaer and @dalelear,
I’m getting exceptions, and in some cases crashes trying to (de)serialise GeometryBase objects in RhinoCommon.
public static byte[] CommonObjectToByteArray(Runtime.CommonObject data)
{
if (data == null)
throw new ArgumentNullException("data");
FileIO.SerializationOptions options = new FileIO.SerializationOptions();
options.RhinoVersion = 4;
options.WriteUserData = true;
StreamingContext context = new StreamingContext(StreamingContextStates.All, options);
MemoryStream stream = new MemoryStream();
Formatters.Binary.BinaryFormatter formatter = new Formatters.Binary.BinaryFormatter(null, context);
formatter.Serialize(stream, data); // <-- Exception
stream.Close();
return stream.GetBuffer();
}
The exception is as follows:
{System.ArgumentNullException: Value cannot be null.
Parameter name: source
at System.Runtime.InteropServices.Marshal.CopyToManaged(IntPtr source, Object destination, Int32 startIndex, Int32 length)
at Rhino.Runtime.CommonObject.SerializeWriteON_Object(IntPtr pConstOnObject, SerializationInfo info, StreamingContext context)
at Rhino.Runtime.CommonObject.GetObjectData(SerializationInfo info, StreamingContext context)
at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder)
at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph)
at Grasshopper.Kernel.GH_Convert.CommonObjectToByteArray(Int32 rhinoVersion, CommonObject data) in C:\dev\grasshopper\1.0\root\src\GH_Convert.vb:line 792}
I’ve started calling this method in a loop and incrementing the options.RhinoVersion each time (first 4, then 5, then 6). I found that on Rhino 5, serialisation of some curves I’ve got only works if the version is set to 6. I do not know how it’s even legal to use 6 while running on Rhino5, but there you go.
However now the problem becomes deserialisation. If I use the same trick trying to deserialise the byte into a GeometryBase instance, there’s an exception that doesn’t cross the unmanaged/managed boundary and it crashes Rhino. I’ve tried stepping into the code, but I’m not getting anywhere sensible.
I’ve attached a Rhino5 3DM file which contains a single curve that will only serialize using RhinoVersion=6 on Rhino5. Trying to deserialize the resulting byte using RhinoVersion=4 will crash.
CurveWhichDoesNotSerialize.3dm (167.2 KB)