But I can not find a function in the gobject-introspection API to get the ref function like âgtk_expression_refâ.
So would the only way to find it be scanning all the available functions/methods of the class/struct/union and grep the function by name containing ârefâ?
[EDIT]
Actually I get the feeling that GtkExpression is the only none GObject based class that supports ref() and unref() operation currently? Well then it is not really hard to find the matching functions.
GIObjectInfo is not exclusive to GObject: it covers all classed types that inherit from GTypeInstance. Thatâs why the ref/unref and set/get-value data is attached to it.
The documentation in libgirepository is, sadly, out of date.
Nope, thereâs also:
GskRenderNode
GdkEvent
which are GTypeInstance derived types with ref/unref functions.
with first parameter GskTransform *next and annotation [allow-none][transfer full]. Because of âtransfer fullâ we have to ensure that the Nim Garbage Collector does not try to free() the next parameter. I think we should do that best by calling gsk-transform-ref().
And for finding the ref functions we may need code like
proc findRefFunctionName(info: GICallableInfo): string =
if gBaseInfoGetType(info) == GIInfoType.Object:
if gObjectInfoGetFundamental(info) == GFalse:
result = "g_object_ref"
else:
if moduleNameSpace == "gtk" and gBaseInfoGetName(info) == "Expression":
result = "gtk_expression_ref"
elif gBaseInfoGetType(info) == GIInfoType.STRUCT:
if moduleNameSpace == "gsk" and gBaseInfoGetName(info) == "Transform":
result = "gsk_transform_ref"
Donât do pattern matching: the type data has the ref/unref functions. If it doesnât, then you should file a bug against the library providing the introspection data.
For boxed types, like GskTransform, use g_boxed_copy() and g_boxed_free().
Yes, for boxed types I am using g_boxed_free(). But I think there is not g_boxed_unref().
The point is that I need a ref() in some rare cases when a function with âtransfer fullâ takes over the function argument. The actual example to which someone pointed me recently was from listview_clocks.c the line
That gtk_expression_ref() we would not want to use manually in higher level languages like Nim. gtk_expression_bind() is another example from that file with âtransfer fullâ.
I simplified strategy, which is currently used in the Nim GTK bindings, is to make the Nim Garbage-Collector just to ignore that entity after a âtransfer fullâ. That works, but the user should not continue using that entity then. But in the listview_clocks.c example program there are use cases where ref() is called on GtkExpression so that the argument can be used further even with âtransfer fullâ.
So calling ref() seems to be the best solution, and I have to somehow find out the exact ref() function name.
For GtkExpression I found no straight gobject-introspection way to get the function gtk_expression_ref().
Donât fixate on what you think the semantics of the type are: use the provided API.
Just like I told you at the very beginning: g_object_info_get_ref_function() and g_object_info_get_unref_function() will return the ref/unref function for any classed typeâi.e. anything that inherits from GTypeInstance.
Again: stop try to reverse engineer the behaviour from what you think the API does.
I have still no idea what these âcopy functionâ is and when it is used. For instance I have a variable which is a pointer to a GtkExpression, and I pass that pointer to gtk_expression_bind()
The first self parameter is the GtkExpression pointer, and in Nim and in C we pass it just to the function as we would do for an int or a float. In listview_clock.c like
expression = gtk_expression_ref (clock_expression);
/* Now create the widget and bind the expression to it. */
picture = gtk_picture_new ();
gtk_expression_bind (expression, picture, "paintable", picture);
gtk_box_append (GTK_BOX (box), picture);
For the gintro Nim bindings it would be not that different, only that we have an additional Nim proxy object for the GtkExpression. The Nim proxy object is some form of supervisor, when the proxy is finalized or destroyed, it call unref() on the GtkExpression. (Well for true gobjects like widgets it is a bit more complicated due to the toggle_ref stuff).
Currently I do not see where a special copy() function is involved.
Would you suggest that we call g_boxed_copy() on each parameter that we pass to functions? I donât think so?
[Edit2]
Well maybe that is really intended: When we have a âtransfer fullâ for a parameter of boxed type, and g_boxed_copy() is just a ref(), then we can do it?
But GtkExpression is not a boxed type, so what would we use for GObjects as a equivalent for g_boxed_copy()? Is there a g_gobject_copy()? Ah, use g_object_info_get_ref_function() to get the ref() function for the none boxed gobjects then? Maybe.
I can see no other way than guessing the ref() function. GskTransform is not a GObject and not a boxed type, but gsk_transform_rotate() is annotated with âtransfer fullâ for that parameter. So we can guess the ref() function and ref() it, so we can continue using it further, or only detach the Garbage-Collector from it. But for the later the user should not use it any longer, which we can not enforce.
A âcopyâ function for a GBoxed type is the function to be called when creating a copy of a boxed type. What a boxed type considers âa copyâ is entirely implementation-defined: some types perform a full clone (copy the data, recursively); some types perform a shallow clone (copy the container but not the data); some types use a reference count.
You should use g_boxed_copy() every time you have to transfer the ownership of a boxed typeâi.e. for transfer full arguments and return values, you must perform a copy so that your wrapper type can be collected at the end of the scope.
There is no such thing as a ânone boxed gobjectsâ.
Letâs try to sum up things a bit more simply, because you keep ignoring what I write and try to reverse engineer the thing Iâm literally explaining to you:
GBoxed types are plain old data structures with a GType associated to it; they have a copy and and a free function
fundamental class types that inherit from GTypeInstance have a ref and an unref function attached to the GIObjectInfo
classed types that inherit from GObject use g_object_ref() and g_object_unref()
Whenever you have to transfer ownership, you call:
g_boxed_copy(), for a GBoxed type
the specified ref function, for a classed type
g_object_ref(), for a GObject type
There is never a case for âguessingâ the memory management functions for a type in the GObject type system and in the introspection data. The entire point of the type system is to provide you with enough information to perform memory management of types; for newly added fundamental types, the introspection data complements the run time type information.
Thanks for all your explanations, I will read it tomorrow again more carefully, too tired currently
Indeed GskTransform is a boxed type, I was confused because for some other boxed types like GtkTreeIter there is a type cascade listed with GBoxed on top. For GskTransform I did not saw that, sorry.
This is for the case of instance parameters of methods. I will test that, and when it works apply to other function parameters with âtransfer fullâ annotation then also.
i.e. for transfer full arguments and return values,
For âreturn valuesâ I am still a bit unsure, I have to find a concrete function where a g_boxed_copy() would make sense. But at least now I know how to do it.
But wait, gtk_expression_bind() has annotation âtransfer noneâ for the GtkExpressionWatch return value. Maybe in that case I should do exactly the same, that is applying g_boxed_copy() on the return value when it is boxed type.
IMO it is a little unfortunate that these functions are known as âcopyâ functions because they are really âduplicationâ functions, and the name g_boxed_dup would would have been more consistent with the names of well known C functions.
Did you mean to say âi.e. âinâ arguments that are transfer full, âoutâ arguments and return values that are transfer none, etc.â?
Iâm not sure what the scope of this discussion is but it may also be worth noting that there are struct types (as described by record elements in a GIR file) that are not boxed (the record element has no glib:get-type attribute), e.g. GtkAccelKey. Such structs are (hopefully) âflatâ so g_malloc()/memcpy()/g_free() can be used.
Also, thatâs not the full story for struct types due to C arrays. For example, the âoutâ argument colors of the function gtk_color_selection_palette_from_string () is an array where the GdkColor structs are inline so, even though GdkColor is a boxed type, you canât use g_boxed_free to clean up the array whose ownership you received. (Ok, this particular type is deprecated.) Similarly, if there was an example of an âinâ argument with transfer âfullâ whose type was an inline C array of a boxed type, you couldnât use g_boxed_copy () because you need an actual copy operation (in the sense of memcpy) for each array element, not a duplication operation like g_boxed_copy ().
It isnât - what to do with a record element with the attribute disguised="1" is another matter that I didnât mention. However, in this case, I would expect GtkPrintBackend to be described by a class element in the GIR file as it is a GObject.