为什么我的 Gdk/cairo class 导致段错误?
Why is my Gdk/cairo class causing a segfault?
我已经写了一个小 class 来从 base64 编码的 JPEG 字节数组创建一个圆形图像,但它似乎经常导致段错误。这是我能找到的在 GJS 中创建 cairo 表面的最简单方法,尽管我不反对 Clutter,如果它能解决我的问题。
var CircularImage = new Lang.Class({
Name: "CircularImage",
Extends: Gtk.DrawingArea,
_init: function (bytearray, win, size) {
this.parent({
height_request: size,
width_request: size
});
this.size = size;
let image_stream = Gio.MemoryInputStream.new_from_data(
GLib.base64_decode(bytearray),
GLib.free
);
let pixbuf = GdkPixbuf.Pixbuf.new_from_stream(
image_stream,
null
)
pixbuf.scale_simple(this.size, this.size, GdkPixbuf.InterpType.HYPER);
this._surface = Gdk.cairo_surface_create_from_pixbuf(
pixbuf,
0,
win.get_window()
);
this.connect("draw", (widget, cr) => {
this._draw(widget, cr);
return false;
});
},
_draw: function (widget, cr) {
cr.setSourceSurface(this._surface, 0, 0);
cr.arc(this.size/2, this.size/2, this.size/2, 0, 2*Math.PI);
cr.clip();
cr.paint();
}
});
CairoImageSurface 似乎没有销毁函数或信号,我尝试取消引用 pixbuf 以查看是否有帮助,但这会导致错误:
GLib-GObject-WARNING **: g_object_remove_toggle_ref: couldn't find toggle ref 0x7f45456b19e0((nil))
我在一个简单的 Gtk window 中使用过它并且它有效,但它似乎有一半的时间会导致段错误。我对内存管理知之甚少,因为我通常使用垃圾收集语言,所以我只假设这与我没有释放的内存有关。
是否有明显的错误,使用 Clutter 的更简单方法或我可以追踪任意段错误的简单方法?
即使底层库需要,您也不必在 GJS 中处理内存管理。如果你这样做,那就是一个错误。无论如何尝试这样做肯定会导致崩溃。 (因此,如果您看到任何调用 GLib.free()
或 GObject.unref()
的说明,即使在 GJS 文档中 — 它们是从 C 文档自动生成的,不应该存在。)
不幸的是,这些需要您关心内存管理的错误仍然存在,其中两个与您的代码片段相关。
您现在遇到的错误是这个:https://bugzilla.gnome.org/show_bug.cgi?id=747431
相反,做这样的事情:
let image_stream = Gio.MemoryInputStream.new_from_bytes(
GLib.base64_decode(bytearray).toGBytes());
另一个 GJS 错误可能会在以后变得相关,当您连接到 draw
信号时,您当前必须在 Cairo 上下文中调用 cr.$dispose()
否则内存将被泄漏。
我已经写了一个小 class 来从 base64 编码的 JPEG 字节数组创建一个圆形图像,但它似乎经常导致段错误。这是我能找到的在 GJS 中创建 cairo 表面的最简单方法,尽管我不反对 Clutter,如果它能解决我的问题。
var CircularImage = new Lang.Class({
Name: "CircularImage",
Extends: Gtk.DrawingArea,
_init: function (bytearray, win, size) {
this.parent({
height_request: size,
width_request: size
});
this.size = size;
let image_stream = Gio.MemoryInputStream.new_from_data(
GLib.base64_decode(bytearray),
GLib.free
);
let pixbuf = GdkPixbuf.Pixbuf.new_from_stream(
image_stream,
null
)
pixbuf.scale_simple(this.size, this.size, GdkPixbuf.InterpType.HYPER);
this._surface = Gdk.cairo_surface_create_from_pixbuf(
pixbuf,
0,
win.get_window()
);
this.connect("draw", (widget, cr) => {
this._draw(widget, cr);
return false;
});
},
_draw: function (widget, cr) {
cr.setSourceSurface(this._surface, 0, 0);
cr.arc(this.size/2, this.size/2, this.size/2, 0, 2*Math.PI);
cr.clip();
cr.paint();
}
});
CairoImageSurface 似乎没有销毁函数或信号,我尝试取消引用 pixbuf 以查看是否有帮助,但这会导致错误:
GLib-GObject-WARNING **: g_object_remove_toggle_ref: couldn't find toggle ref 0x7f45456b19e0((nil))
我在一个简单的 Gtk window 中使用过它并且它有效,但它似乎有一半的时间会导致段错误。我对内存管理知之甚少,因为我通常使用垃圾收集语言,所以我只假设这与我没有释放的内存有关。
是否有明显的错误,使用 Clutter 的更简单方法或我可以追踪任意段错误的简单方法?
即使底层库需要,您也不必在 GJS 中处理内存管理。如果你这样做,那就是一个错误。无论如何尝试这样做肯定会导致崩溃。 (因此,如果您看到任何调用 GLib.free()
或 GObject.unref()
的说明,即使在 GJS 文档中 — 它们是从 C 文档自动生成的,不应该存在。)
不幸的是,这些需要您关心内存管理的错误仍然存在,其中两个与您的代码片段相关。
您现在遇到的错误是这个:https://bugzilla.gnome.org/show_bug.cgi?id=747431 相反,做这样的事情:
let image_stream = Gio.MemoryInputStream.new_from_bytes(
GLib.base64_decode(bytearray).toGBytes());
另一个 GJS 错误可能会在以后变得相关,当您连接到 draw
信号时,您当前必须在 Cairo 上下文中调用 cr.$dispose()
否则内存将被泄漏。