Yes, that function is deprecated, so maybe not the best example, but I think there are some more functions of this type, and I can not really forbid users to use deprecated functions if they desire…
For this function first parameter is datalength, and second parameter is the data array. But for most functions the parameters are exchanged, first the array, then the length.
I wonder if there is a secure way using gobject-introspection to detect the order? Currently I assume order first array, followed by length. (Of course only for the cases when we need and expect a length parameter, zero terminated arrays and cstring-arrays are handled separately, that works fine.) For a few rare cases like the one mentioned above this fails. First question is, why some functions uses length first – my guess is that author just ignored conventions? Next question is how to detect and automatically fix this case. Maybe just check parameter type after array – when there is none or it is not an integer type, then try parameter before array? Unfortunately coding this exchange for the bindings generator script is not that easy, maybe if these cases are really rare, I will just skip it and code these exceptions manually.
(I have also detected a few cases where two arrays are involved, followed by length parameter – I will see if I can handle this case automatically…)
Seems to work fine for most functions. For a few there seems to exist no array length= entry so that g_type_info_get_array_length() returns -1. But that is not a very big problem. Example is
<doc xml:space="preserve">Replacement for g_io_channel_write() with the new API.
On seekable channels with encodings other than %NULL or UTF-8, generic
mixing of reading and writing is not allowed. A call to g_io_channel_write_chars ()
may only be made on a channel from which data has been read in the
cases described in the documentation for g_io_channel_set_encoding ().</doc>
<doc xml:space="preserve">the status of the operation.</doc>
<type name="IOStatus" c:type="GIOStatus"/>
<instance-parameter name="channel" transfer-ownership="none">
<doc xml:space="preserve">a #GIOChannel</doc>
<type name="IOChannel" c:type="GIOChannel*"/>
<parameter name="buf" transfer-ownership="none">
<doc xml:space="preserve">a buffer to write data from</doc>
<array zero-terminated="0" c:type="const gchar*">
<parameter name="count" transfer-ownership="none">
<doc xml:space="preserve">the size of the buffer. If -1, the buffer
is taken to be a nul-terminated string.</doc>
<type name="gssize" c:type="gssize"/>
<doc xml:space="preserve">The number of bytes written. This can be nonzero
even if the return value is not %G_IO_STATUS_NORMAL.
If the return value is %G_IO_STATUS_NORMAL and the
channel is blocking, this will always be equal
to @count if @count >= 0.</doc>
<type name="gsize" c:type="gsize*"/>
Do you think that is a bug that we may report, or may it be by intent? (I think there are 5 similar issues.)
GIOChannel predates any work on describing a GLib-based C API by many years; the whole of GLib-2.0 (not GObject or GIO) is not really a poster child for introspection, as it is considered a low level C utility API. Most languages already have native replacements for most of GLib, so it’s not really useful to bind it thoroughly.
In this particular case, the count argument for g_io_channel_write_chars() has a complex behaviour; if it’s a positive integer, it’s the length of the uint8 buffer, but if it’s -1 then the function will consider the buffer a NUL-terminated C string, and compute its length automatically. This is why the function is not annotated.
Ideally, you could always consider an array of uint8 elements without a length as a NUL-terminated string, but in practice it depends on the semantics of the function.