Wrong returns from get_iter() method when try to implement Gtk.TreeModel interface directly in JS
I try to implement methods of Gtk.TreeModel interface to make a custom data model in JS. 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 way to create an instance of Gtk.TreeIter in JS. To create an instance 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);
}
The implementation of Gtk.TreeModel methods in JS happens in CustomList class:
iter-test.js
imports.gi.versions.Gtk = '3.0';
const { GObject, GLib, Gtk } = imports.gi;
const Gtkextra = imports.gi.Gtkextra;
const assert = imports.jsUnit.assert;
const sys = imports.system;
Gtk.init(null);
const CustomList = GObject.registerClass({
Implements: [Gtk.TreeModel]
},
class CustomList extends GObject.Object {
_init () { super._init (); }
vfunc_get_iter (path) { // Gtk.TreePath
print ("in get_iter");
const iter = Gtkextra.new_iter ();
Gtkextra.set_iter_stamp (iter, 10);
Gtkextra.set_iter_user_data2 (iter, "hello");
print (iter);
print ("iter.stamp =", iter.stamp);
print ("iter.stamp =", Gtkextra.get_iter_stamp (iter));
print (Gtkextra.get_iter_user_data2 (iter) );
print ("our get_iter");
return [true, iter];
}
}
);
const custom_list = new CustomList ();
let path = Gtk.TreePath.new_from_string ("0");
print ("test - get_iter ()");
/* get_iter () */
let [res, iter] = custom_list.get_iter (path);
print ();
print ("res =", res);
print (iter);
print ("iter.stamp =", iter.stamp);
print ("iter.stamp =", Gtkextra.get_iter_stamp (iter));
print ("iter.stamp = 0x" + iter.stamp.toString (16));
print ("iter.user_data2 =", iter.user_data2);
//print ("iter.user_data2 =", print (Gtkextra.get_iter_user_data2 (iter))); // segfault
$ gjs iter-test-1.js
test - get_iter ()
in get_iter
in set_iter_stamp
iter address: 0x13b5610
out set_iter_stamp
[boxed instance proxy GIName:Gtk.TreeIter jsobj@0xb1377720 native@0x13b5610]
iter.stamp = 10
iter.stamp = 10
hello
our get_iter
res = true
[boxed instance proxy GIName:Gtk.TreeIter jsobj@0xb1377740 native@0x13b5620]
iter.stamp = 20665872
iter.stamp = 20665872
iter.stamp = 0x13b5610
iter.user_data2 = undefined
From the output of the script we can see that the out parameter 'iter' got the right structure object, but the iter.stamp field has the address native@0x13b5610 instead of value 10. And iter.user_data2 field is NULL.
The same script in Python3 returns the structure with the right value in iter.stamp field, but wrong value in iter.user_data2 field.