Re: [Vala] How to use the ZLib bindings?



Hi Yu,

On Mon, Nov 9, 2009 at 7:12 PM, Feng Yu <rainwoodman gmail com> wrote:
On Sun, Oct 4, 2009 at 7:25 AM, Philipp Zabel <pzabel gmx de> wrote:

Hi,

Does anybody have example code that uses the ZLib bindings? I tried to
implement the example described at http://zlib.net/zlib_how.html for
inflation, but compilation failed with errors from gcc about STATUS_OK
etc. symbols not being found. The following patch helped with that for
some reason.

Also, I don't understand how Vala can handle memory for the next_in and
next_out pointers when the inflate call is changing those pointers under
its nose. Wouldn't it be more realistic not to wrap them as an array?


I believe old vapi binding for next_in and next_out still works. Vala don't
manage the memory of struct types declared in vapi files.

If you are sure the buffer is not owned by the struct and you want to
explicitly mention this in the vapi file, use 'unowned'. Change the
signature to 'unowned uchar[]' in this case.

Yes, you are right. With the following patch (against 0.7.8) ...

diff --git a/vapi/zlib.vapi b/vapi/zlib.vapi
index bb85db7..db9579d 100644
--- a/vapi/zlib.vapi
+++ b/vapi/zlib.vapi
@@ -90,10 +90,11 @@ namespace ZLib {
        }
        [CCode (cname = "z_stream", destroy_function = "deflateEnd")]
        public struct Stream {
-               public uchar* next_in;
-               public uint avail_in;
+               [CCode (array_length_cname = "avail_in", array_length_type = "guint")]
+               public weak uchar[] next_in;
                public ulong total_in;
-               public uchar* next_out;
+               [CCode (array_length_cname = "avail_out", array_length_type = "guint")]
+               public weak uchar[] next_out;
                public uint avail_out;
                public ulong total_out;
                public string? msg;

.. I can also make my example work if I assign to the weak uchar array's length:

        InputStream source = File.new_for_path ("test.gz").read (null);
        uchar[] buf_in = new uchar[16384];
        uchar[] buf_out = new uchar[16384];

        var strm = InflateStream.full (15 | 32);   // no way to check if this failed...

        strm.next_in = buf_in;
        strm.next_out = buf_out;
        strm.next_in.length = (int) source.read (strm.next_in,
strm.next_in.length, null);
        // ^ ^ ^ ^ ^ ^ ^ here
        if (strm.next_in.length == 0)
                return;
        int ret = strm.inflate (Flush.NO_FLUSH);

I still maintain that strm.next_in / strm.next_out cannot be owned
arrays because the call to strm.inflate changes the pointers
themselves. The same program compiles unchanged when I remove the weak
keywords again, but it fails when trying to destroy the buffers:
*** glibc detected *** ./zlibtest: munmap_chunk(): invalid pointer:
0x000000000210b500 ***

Please avoid pointers if possible in vapi bindings. Pointers forces
programers write '->'s and makes the code C++-ish.

The '->' argument doesn't apply here - uchar* vs uchar[], no structs involved.
But I agree that a single weak uchar[] is more Valaish than a uchar* and an int.
The initial assignment is more compact this way:
        strm.next_out = buf_out;
vs
        strm.next_out = buf_out;
        strm.avail_out = buf_in.length;
And I have to replace strm.avail_out with stream.next_out.length.
Other than that,
it's the same. So should we change that back (to weak uchar[]s)?

Remember your vapi file is going to be used by others and will affect their
programming styles. The influence might be permanent.

Thanks for having a look at this.

regards
Philipp

Attachment: zlibtest.vala
Description: Text Data



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]