Skip to content
This repository has been archived by the owner on Jun 8, 2021. It is now read-only.

GResource bindings #120

Closed
sunnyone opened this issue Mar 26, 2016 · 8 comments
Closed

GResource bindings #120

sunnyone opened this issue Mar 26, 2016 · 8 comments

Comments

@sunnyone
Copy link

Does a plan exist to support GResource apis?

Nowadays some of gtk apis have _from_resource variations, so embedding GResource bytes with include_bytes! is convinient in gtk-rs programming.

Currently I use GResource with -sys crates directly, but it's ugly (the code is below).

let res_bytes = include_bytes!("resources/resources.gresource");
unsafe {
    // gbytes and resource will not be freed
    let gbytes = glib_sys::g_bytes_new(res_bytes.as_ptr() as *const libc::c_void, res_bytes.len());
    let resource = gio_sys::g_resource_new_from_data(gbytes, std::ptr::null_mut());
    gio_sys::g_resources_register(resource);
}

(the full project source is here: https://github.com/sunnyone/gresource-gtkrs-example)

I lack the knowledge of Rust to create GResource binding, especially a part to determine correct lifetime of GResource. I hope a GResource binding will be implemented smartly.

@GuillaumeGomez
Copy link
Member

Binding GTypes is quite difficult and it takes time to determine what's the best way to do it. It'll be done, but I don't know when.

cc @gkoz

@gkoz
Copy link
Member

gkoz commented Mar 26, 2016

We'll generate some gio classes soon. I'll keep an eye on this.

@sunnyone I think you can avoid extra copying by changing g_bytes_new to g_bytes_new_static because include_bytes returns &'static [u8; N].

@sunnyone
Copy link
Author

Thanks for replies and a advice! I'm looking forward to using new classes.

@gkoz
Copy link
Member

gkoz commented Apr 26, 2016

The safe translation of the above should now be

let bytes = glib::Bytes::from_static(include_bytes!("resources/resources.gresource"));
let res = gio::Resource::new_from_data(&bytes).unwrap();
gio::resources_register(&res);

@sunnyone
Copy link
Author

Thanks!

@thk1
Copy link

thk1 commented Sep 28, 2016

I like this feature especially since it spares me keeping struggling with platform dependent resource paths. However I'm having some issues because Glib seems to need 8-byte-aligned data. If the data included via include_bytes!() is not aligned, the program crashes as soon as a resource is referenced in a Builder UI description or from code, e.g. via Builder::new_from_resource(...):

GLib:ERROR:/build/glib2.0-7IO_Yw/glib2.0-2.48.1/./glib/gvariant-serialiser.c:167:g_variant_serialised_check: assertion failed (alignment & (gsize) serialised.data == 0): (5 == 0)

The C source file generated by glib-compile-resources resources.gresource.xml --generate-source assures aligned data with the following line:

# define SECTION __attribute__ ((section (".gresource.res"), aligned (8)))

Unfortunately, Rust's #[repr(align = "64")] proposal hasn't landed yet. In nightly Rust you can use the hack from here. But in stable Rust my code only works if the compiler has coincidentally put the gresource bytes at the right location. Do you have any ideas how to solve this?

@thk1
Copy link

thk1 commented Sep 28, 2016

I've got a temporary solution: If glib::Bytes copies the static data, it seems to be aligned (however I haven't found any documentation on this).

// first make &[u8;...] unsized because &[u8;N] doesn't implement std::borrow::Borrow<[T]> for N>32
let resource_data: &[u8] = &include_bytes!("../res/res.gresource")[..];
let bytes = glib::Bytes::from(&resource_data);
let res = gio::Resource::new_from_data(&bytes).unwrap();
gio::resources_register(&res);

Is there a reason for glib::Bytes::new() not being public? Using new() directly the first line (&...[..]) shouldn't be necessary.

@gkoz
Copy link
Member

gkoz commented Sep 28, 2016

If the data included via include_bytes!() is not aligned,

Yeah, I've encountered this in this build-helper prototype. I had to forego include_bytes! and use array syntax (not that it matters much, it's automated anyway). The only solution I can see is to ask rustc folks for an optional alignment argument. So far this is the only use case for such an extension I'm afraid.

If glib::Bytes copies the static data, it seems to be aligned

I suppose large allocations are likely to be aligned but one can't really depend on that.

Is there a reason for glib::Bytes::new() not being public? Using new() directly the first line (&...[..]) shouldn't be necessary.

Not sure now but it might be making new copy data didn't feel right and I wanted to leave other options on the table.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants