Gobject-introspection, array parameter with length parameter before array

One example is

https://developer.gnome.org/gdk-pixbuf/stable/gdk-pixbuf-Image-Data-in-Memory.html#gdk-pixbuf-new-from-inline

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…)

The introspection annotation for that function is already correct:

 * @data_length: Length in bytes of the @data argument or -1 to 
 *    disable length checks
 * @data: (array length=data_length): Byte data containing a
 *    serialized #GdkPixdata structure

i.e. the length of the data argument is provided by the data_length argument. In the GIR the parameters are:

          <parameter name="data_length" transfer-ownership="none">
            <doc xml:space="preserve"
                 filename="gdk-pixbuf/gdk-pixdata.c"
                 line="933">Length in bytes of the @data argument or -1 to
   disable length checks</doc>
            <type name="gint" c:type="gint"/>
          </parameter>
          <parameter name="data" transfer-ownership="none">
            <doc xml:space="preserve"
                 filename="gdk-pixbuf/gdk-pixdata.c"
                 line="935">Byte data containing a
   serialized #GdkPixdata structure</doc>
            <array length="0" zero-terminated="0" c:type="const guint8*">
              <type name="guint8" c:type="guint8"/>
            </array>
          </parameter>

The length attribute of the data parameter points to the first parameter (the parameters index starts from 0).

When using libgirepository, the argument that defines the length of the array can be retrieved using g_type_info_get_array_length().

That is great information! So array length=“0” tells us that length of array is defined by parameter 0, and we can get that info by g_type_info_get_array_length().

I was not able to guess that from the api docs:

https://developer.gnome.org/gi/stable/gi-GITypeInfo.html#g-type-info-get-array-length

How have you manage to copy a section of /usr/share/gir-1.0/Gtk-3.0.gir sytax highlighted into this forum? I have copied short sections myself, but it was looking not nice.

Please, file a bug for clarifying the documentation.

Use the markdown syntax for specifying the highlighting to be applied to a code block, e.g.

```xml
<some><xml goes="here"/></some>
```

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

      <method name="write_chars"
              c:identifier="g_io_channel_write_chars"
              throws="1">
        <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>
        <return-value transfer-ownership="none">
          <doc xml:space="preserve">the status of the operation.</doc>
          <type name="IOStatus" c:type="GIOStatus"/>
        </return-value>
        <parameters>
          <instance-parameter name="channel" transfer-ownership="none">
            <doc xml:space="preserve">a #GIOChannel</doc>
            <type name="IOChannel" c:type="GIOChannel*"/>
          </instance-parameter>
          <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*">
              <type name="guint8"/>
            </array>
          </parameter>
          <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"/>
          </parameter>
          <parameter name="bytes_written"
                     direction="out"
                     caller-allocates="0"
                     transfer-ownership="full">
            <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 &gt;= 0.</doc>
            <type name="gsize" c:type="gsize*"/>
          </parameter>
        </parameters>
      </method>

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.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.