Re: Marshaling (inout) structs/objects



On 26/10/2016 20:23, Iñaki García Etxebarria wrote:
In writing the Haskell bindings for gobject-introspection I ran into some
apparent ambiguity, and I cannot find a discussion of this point in the
gobject-introspection annotation specs, so I wanted to ask what other languages
are doing/what is best practice.

For simple scalar types, such as gint, it is clear that (inout) means that the
argument of the function is of type "gint*", and that the value pointed to by
the argument may be overwritten by the callee.

But for more complex types represented by pointers, for example structs such as
"PangoRectangle", what does type="Rectangle" direction="inout" mean in the GIR
file? In the introspection data there seem to be two interpretations:

(a) An argument of type "PangoRectangle*" that gets modified by the function.
(An example is pango_matrix_transform_pixel_rectangle )

What you describe is an (in) parameter (that is destructively updated). pango_matrix_transform_pixel_rectangle is incorrectly annotated. I suspect the author of the annotation was thinking about the flow of information rather than the actual passing of a parameter of type PangoRectangle*.


(b) An argument of type "PangoRectangle**". The value of the "PangoRectangle*"
pointer inside the passed in argument gets overwritten. (An example is
gtk_widget_destroyed.)

(inout) must be this.


In other words, in these cases it seems not clear whether (inout) refers to
mutability of the contents pointed to by the struct pointer, or of the pointer
itself.

(inout) does not refer to mutability.

Hopefully you would see "const PangoRectangle*" as the type for an (in) parameter that is not destructively updated but I don't believe that GIR metadata captures that information.


(At least for the Haskell bindings mutability information for the contents is
pointless, since we don't attempt to convert C type structs into pure records,
we just keep the pointer around and access the corresponding memory location
when one is interested in reading/writing fields, as C would.)

Sounds like it isn't a problem assuming any C struct is mutable.


Does any existing binding care about interpretation (a)? If so, it may be
clearer to introduce a separate annotation ("(modified)" or something like that)
to disentangle the two possible interpretations. Otherwise we could perhaps
settle on interpretation (b), so there is a uniform interpretation of what
(inout) means for all types.

An (inout) annotation can only have interpretation (b). (inout) means that a value of the parameter type is given to an argument before the function is called and taken from the argument after the function returns. To achieve this, an extra level of indirection is present in the C argument type.

A struct is passed by reference, so the C type is a pointer to the struct, e.g. PangoRectangle*. With (a), it is not possible to pass back a PangoRectangle*. For example, with (a) it would not be possible to pass back NULL if the parameter specified (nullable).

Phil



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