Wrong returns from get_iter() method when try to implement Gtk.TreeModel interface directly in Python
public abstract bool get_iter (out TreeIter iter, TreePath path);
I try to implement methods of Gtk.TreeModel interface to make a custom data model directly in Python without use of generictreemodel module. While doing this I found an error in returns value of structure Gtk.TreeIter in method get_iter(). The structure has the following fields and methods:
Fields:
public int stamp
public void* user_data
public void* user_data2
public void* user_data3
Methods:
public TreeIter? copy ()
public void free ()
Note that there is no explicit way to create an instance of Gtk.TreeIter in Python. To make this I made a library libgtkextra-0.1.so in Vala with the following functions:
namespace Gtkextra {
public static void new_iter (out Gtk.TreeIter iter);
public static void set_iter_stamp (ref Gtk.TreeIter iter, int stamp);
public static int get_iter_stamp (Gtk.TreeIter iter);
public static void set_iter_user_data (ref Gtk.TreeIter iter, GLib.Object user_data);
public static GLib.Object get_iter_user_data (Gtk.TreeIter iter);
public static void set_iter_user_data2 (ref Gtk.TreeIter iter, GLib.Value user_data);
public static GLib.Value get_iter_user_data2 (Gtk.TreeIter iter);
public static void set_iter_user_data3 (ref Gtk.TreeIter iter, GLib.Value user_data);
public static GLib.Value get_iter_user_data3 (Gtk.TreeIter iter);
...
public void set_iter_stamp (ref Gtk.TreeIter iter, int stamp) {
print ("in set_iter_stamp\n");
print ("iter address: 0x%x\n\n", (int)&iter);
iter.stamp = stamp;
print ("out set_iter_stamp\n");
}
...
public GLib.Object get_iter_user_data (Gtk.TreeIter iter) {
print ("\nin get_iter_user_data\n");
print ("iter.stamp = %d\n", iter.stamp);
print ("iter.user_data address = 0x%d\n", (int)iter.user_data);
print ("iter.user_data2 address = 0x%d\n", (int)iter.user_data2);
print ("iter.user_data3 address = 0x%d\n", (int)iter.user_data3);
Gtk.Label* lbl = (Gtk.Label*)iter.user_data;
print (lbl->label + "\n");
print ("out get_iter_user_data\n");
return (GLib.Object)iter.user_data;
}
...
}
The implementation of Gtk.TreeModel methods in Python happens in CustomList class:
iter-test.py
import gi
gi.require_version("Gtk", "3.0")
gi.require_version("Gtkextra", "0.1")
from gi.repository import Gtk, GLib, GObject, Gtkextra
import sys
#Gtk.init(None)
class CustomList(GObject.GObject, Gtk.TreeModel):
def __init__(self):
GObject.GObject.__init__(self)
def do_get_iter (self, path):
print ("in get_iter")
itr = Gtkextra.new_iter ()
Gtkextra.set_iter_stamp (itr, 10)
lbl = Gtk.Label (label = "Hello")
Gtkextra.set_iter_user_data (itr, lbl)
l = Gtkextra.get_iter_user_data (itr)
print (l.props.label)
val = GObject.Value ()
val.init (GObject.TYPE_STRING);
val.set_string ("hello");
Gtkextra.set_iter_user_data2 (itr, val)
print (itr)
print ("iter.stamp =", itr.stamp)
print ("iter.stamp =", Gtkextra.get_iter_stamp (itr))
print (Gtkextra.get_iter_user_data (itr).props.label)
print (Gtkextra.get_iter_user_data2 (itr) )
print ("iter.user_data =", itr.user_data)
print ("iter.user_data2 =", itr.user_data2)
print ("iter.user_data3 =", itr.user_data3)
print ("out get_iter")
return True, itr
GObject.type_register(CustomList)
custom_list = CustomList ()
path = Gtk.TreePath.new_from_string ("0")
print ("\ntest - get_iter ()")
res, itr = custom_list.do_get_iter (path)
print ()
print ("res =", res)
print (itr)
print ("iter.stamp =", itr.stamp)
print ("iter.stamp =", Gtkextra.get_iter_stamp (itr))
print ("iter.user_data =", itr.user_data)
print ("iter.user_data2 =", itr.user_data2)
print ("iter.user_data3 =", itr.user_data2)
l = Gtkextra.get_iter_user_data (itr)
print (l.props.label)
print ("iter.user_data2 =", itr.user_data2)
#print ("iter.user_data2 =", print (Gtkextra.get_iter_user_data2 (itr))) # segfault
print ("iter.user_data3 =", itr.user_data3)
The script returns the structure with the right value in iter.stamp field, but wrong values in iter.user_data and iter.user_data2 fields.
serg@serg-netbook:~/progr/libgtkextra/examples$ python3 iter-test.py
test - get_iter ()
in get_iter
in set_iter_stamp
iter address: 0x8f1e8d0
out set_iter_stamp
in get_iter_user_data
iter.stamp = 10
iter.user_data address = 0x150495496
iter.user_data2 address = 0x0
iter.user_data3 address = 0x0
Hello
out get_iter_user_data
Hello
<Gtk.TreeIter object at 0xb6f2d14c (GtkTreeIter at 0x8f1e8d0)>
iter.stamp = 10
iter.stamp = 10
in get_iter_user_data
iter.stamp = 10
iter.user_data address = 0x150495496
iter.user_data2 address = 0x151064696
iter.user_data3 address = 0x0
Hello
out get_iter_user_data
Hello
hello
iter.user_data = 150495496
iter.user_data2 = 151064696
iter.user_data3 = 0
out get_iter
res = True
<Gtk.TreeIter object at 0xb6f2d14c (GtkTreeIter at 0x8f1e8d0)>
iter.stamp = 10
iter.stamp = 10
iter.user_data = 150495496
iter.user_data2 = 151064696
iter.user_data3 = 151064696
in get_iter_user_data
iter.stamp = 10
iter.user_data address = 0x150495496
iter.user_data2 address = 0x151064696
iter.user_data3 address = 0x0
(iter-test.py:12793): Gtk-CRITICAL **: 21:11:33.331: gtk_label_get_label: assertion 'GTK_IS_LABEL (label)' failed
(null)out get_iter_user_data
iter-test.py:60: Warning: invalid unclassed pointer in cast to 'GObject'
l = Gtkextra.get_iter_user_data (itr)
iter-test.py:60: Warning: g_object_ref: assertion 'G_IS_OBJECT (object)' failed
l = Gtkextra.get_iter_user_data (itr)
Traceback (most recent call last):
File "iter-test.py", line 61, in <module>
print (l.props.label)
AttributeError: 'NoneType' object has no attribute 'props'
As we can see from the output the fields iter.user_data and iter.user_data2 have right address, but wrong objects.