Hi Yu,
On Mon, Nov 9, 2009 at 7:12 PM, Feng Yu <[email protected]> wrote:
> On Sun, Oct 4, 2009 at 7:25 AM, Philipp Zabel <[email protected]> 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
using GLib;
using ZLib;
class ZLibTest : Object {
// 16KB buffer size
const int CHUNK = 16*1024;
uchar[] buf_in;
uchar[] buf_out;
construct {
buf_in = new uchar[CHUNK];
buf_out = new uchar[CHUNK];
}
public int inflate (InputStream source, OutputStream dest) throws Error {
uint have;
int ret = Status.OK;
var strm = InflateStream.full (15 | 32); // no way to check if this failed...
// decompress until deflate stream ends or end of file
do {
strm.next_in = buf_in;
strm.next_in.length = (int) source.read (strm.next_in, strm.next_in.length, null);
if (strm.next_in.length == 0)
break;
// run inflate() on input until output buffer not full
do {
strm.next_out = buf_out;
ret = strm.inflate (Flush.NO_FLUSH);
assert (ret != Status.STREAM_ERROR); // state not clobbered
if (ret == Status.NEED_DICT)
ret = Status.DATA_ERROR; // and fall through
switch (ret) {
case Status.DATA_ERROR:
case Status.MEM_ERROR:
return ret;
}
have = CHUNK - strm.next_out.length;
if (dest.write (buf_out, have, null) != have)
return Status.ERRNO;
} while (strm.avail_out == 0);
// done when inflate () says it's done
} while (ret != Status.STREAM_END);
return ret == Status.STREAM_END ? Status.OK : Status.DATA_ERROR;
}
public static int main (string[] argv) {
var zlib_test = new ZLibTest ();
var infile = File.new_for_path ("test.gz");
var outfile = File.new_for_path ("test.jpg");
InputStream instream;
OutputStream outstream;
try {
instream = infile.read (null);
outstream = outfile.create (FileCreateFlags.NONE, null);
return zlib_test.inflate (instream, outstream);
} catch (Error e) {
stderr.printf ("Error: %s\n", e.message);
return -1;
}
}
}
_______________________________________________
Vala-list mailing list
[email protected]
http://mail.gnome.org/mailman/listinfo/vala-list