Can't compress with mono?
Asked Answered
D

2

7

I'm trying to compress some data in mono like this:

public static string Save(FlightProgram program, bool compressed)
{
    using (MemoryStream ms = new MemoryStream())
    {
        BinaryFormatter f = new BinaryFormatter();
        if (compressed)
        {
            using (DeflateStream gz = new DeflateStream(ms, CompressionMode.Compress))
            {
                f.Serialize(gz, program);
            }
        }
        else
        {
            f.Serialize(ms, program);
        }
        return Convert.ToBase64String(ms.ToArray()).Replace('/', '_');
    }
}

I'm simply getting the exception "CreateZStream". No inner exception. What's going on here ?

Stacktrace:

Could not save flight program: CreateZStream at   at (wrapper managed-to-native) System.IO.Compression.DeflateStream:CreateZStream (System.IO.Compression.CompressionMode,bool,System.IO.Compression.DeflateStream/UnmanagedReadOrWrite,intptr)
    at System.IO.Compression.DeflateStream..ctor (System.IO.Stream compressedStream, CompressionMode mode, Boolean leaveOpen, Boolean gzip) [0x00000] in <filename unknown>:0 
    at System.IO.Compression.DeflateStream..ctor (System.IO.Stream compressedStream, CompressionMode mode) [0x00000] in <filename unknown>:0 
    at KSPComputerModule.ProgramSerializer.Save (KSPComputer.FlightProgram program, Boolean compressed) [0x00000] in <filename unknown>:0 
    at KSPComputerModule.FPComputer.OnSave (.ConfigNode node) [0x00000] in <filename unknown>:0  (State: None)
Dennisedennison answered 30/10, 2014 at 20:22 Comment(1)
I don't actually know how Unity works, but I guess they look at the IL code and re-compile/re-link it. Maybe they don't support the System.IO.Compression fully (see: forum.unity3d.com/threads/… )Dyche
C
6

Surely not relevant to the OP anymore...but I finally managed to resolve this myself. It's a bug in the Mono for Windows deployment. If you delete MonoPosixHelper.dll files from Mono/GtkSharp directories, you'll find suddenly it works. Running Process Monitor, you can see that instead of going for the mal-compiled MonoPosixHelper.dll, it now goes for libMonoPosixHelper.dll...which is compiled correctly.

So, to resolve permanently, either delete all MonoPosixHelper.dll files so it uses libMonoPosixHelper.dll...or, preferably, use a dllmap, adding

 <dllmap dll="MonoPosixHelper" target="libMonoPosixHelper.dll" os="windows" />

to either C:\Program Files (x86)\Mono\lib\mono\gac\System\4.0.0.0__b77a5c561934e089\System.dll.config(create if it doesn't already exist) or to the global Mono config at C:\Program Files (x86)\Mono\etc\mono\config

Churchlike answered 5/10, 2015 at 22:22 Comment(0)
S
5

I've tested it myself and i get a DllNotFoundException:

System.DllNotFoundException: MonoPosixHelper
  at (wrapper managed-to-native) System.IO.Compression.DeflateStream:CreateZStream (System.IO.Compression.CompressionMode,bool,System.IO.Compression.DeflateStream/UnmanagedReadOrWrite,intptr)
  at System.IO.Compression.DeflateStream..ctor (System.IO.Stream compressedStream, CompressionMode mode, Boolean leaveOpen, Boolean gzip) [0x00000] in <filename unknown>:0 
  at System.IO.Compression.DeflateStream..ctor (System.IO.Stream compressedStream, CompressionMode mode) [0x00000] in <filename unknown>:0 
  at (wrapper remoting-invoke-with-check) System.IO.Compression.DeflateStream:.ctor (System.IO.Stream,System.IO.Compression.CompressionMode)

The reason seems to be the CreateZStream function which is an external method which should be defined inside the MonoPosixHelper.dll.

CreateZStream is declared as

[DllImport("__Internal", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr CreateZStream(CompressionMode compress, bool gzip, DeflateStream.UnmanagedReadOrWrite feeder, IntPtr data);

However the file "MonoPosixHelper.dll" doesn't exist. There's a libMonoPosixHelper.dylib which seems to implement an entry point for CreateZStream, however that's a library for mac.

Personally i had bad experiences with most compression code / libraries in Unity as most implementations simply wrap a native code library. According to the compatibility page the class is supported, however it looks like only the managed part is implemented. This one also seems to verify that.

I've successfully used the SharpZipLib library in a lot of projects. It's a pure managed library without native code dependencies. I've used this library in standalone, web, android and iOS builds without any problems.

Skive answered 31/10, 2014 at 5:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.