Giter VIP home page Giter VIP logo

glib's Introduction

glib Build Status Build status Gitter

GLib bindings for Rust.

Alongside GLib bindings, this crate also includes the infrastructure to subclass GObject for extending libraries like GTK+. A code example can be found in the documentation of this crate in the subclass module.

License

MIT

glib's People

Contributors

andy128k avatar antoyo avatar bilelmoussaoui avatar bpbp-boop avatar buster avatar bvinc avatar dndanik avatar dvhaeren avatar epashkin avatar federicomenaquintero avatar fengalin avatar gkoz avatar gsingh93 avatar guillaumegomez avatar hfiguiere avatar ids1024 avatar jeremyletang avatar jgillich avatar kinnison avatar luukvanderduim avatar mathijshenquet avatar oakes avatar osa1 avatar philn avatar sdroege avatar susurrus avatar tmiasko avatar vojtechkral avatar xanathar avatar zeenix avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

glib's Issues

glib::Bytes::from_static segfaults at runtime when a `&'static [u8; N]` array is passed instead of &'static u8.

When passing the result of a include_bytes! macro, which is &'static [u8; N], into Bytes::from_static(&'static u8) it compiles fine but segfaults at runtime with error message:

GLib:ERROR:gvariant-serialiser.c:167:g_variant_serialised_check: assertion failed (alignment & (gsize) serialised.data == 0): (5 == 0)

When you explicitly specify Bytes::from_static(res_bytes.as_ref()), where as_ref makes [u8, N] into u8 it works fine.

I forked an example repo and replicated the bug here

git clone https://github.com/alatiera/gresource-gtkrs-example.git
cd gresource-gtkrs-example
cargo run

Crate versions I used:
gio = "0.2"
glib "0.2"

Connect internals

As I am running into issues with the current implementation of Connect (cfr. gtk-rs/gtk#30), I am looking at the implementation to see if I can pin-point the origin of my issues. However, within that code you can find:

ffi::glue_signal_connect(
                self.unwrap_gobject(),
                signal_name.borrow_to_glib().0,
                Some(trampoline),
                user_data_ptr
            );

Which can also be found among the FFI defintions:

    pub fn glue_signal_connect(g_object: *mut C_GObject,
                               signal: *const c_char,
                               func: Option<extern "C" fn()>,
                               user_data: *const c_void);

What exactly is glue_signal_connect? I'm asking because I can't seem to find this in Glib.

Furthermore, the Signal trait seems to have a fetch_cb method. What should this be used for? As I don't see it being used (directly) at the moment. (They are used to create the trampolines).

Cast/Downcast traits are unnecessarily restrictive

Two problems here:

  • Currently upcast() works exclusively on the IsA<_> trait. That is, you can only upcast from A to B, if A: IsA<B>. Upcasting is used (1) for going from a subclass to a parent class, or (2) for going from some class to an interface implemented by it.
    Case (1) should always work fine, as it will be statically known that A: IsA<B> if both types are represented in Rust.
    Case (2) however will fail easily: Consider a function that returns an object of type A according to its signature, but actually returns an object of a subclass X of A and X is not defined anywhere in Rust (might not even be in C headers or anywhere). This is the case for various things in GIO, and GStreamer elements.

The same also happens if you have an object of type A, stored in a variable of type B (B is the parent class of A). A implements interface C (and this is statically known) but B does not. You can't cast from B to C currently.

  • Similarly, downcast() currently only works if there is a IsA relationship statically known between the types. Which fails in the same cases as above.

I would suggest that we deprecate/remove these traits and instead just have

  • a cast() function that can cast between anything and checks at runtime (similar to downcast right now). This could be in ObjectExt also. The distinction between upcast and downcast is not really relevant here as you always have to check at runtime anyway for interfaces at least, and it can always fail.
  • optionally a static_upcast() function (equivalent to the old upcast()) which only looks at the IsA<_> traits, and can because of that only support statically known upcasting (and never downcasting). This could be a free function, a new trait that is implemented for everything that implements IsA<_>, ...
  • static_downcast (equivalent to the old downcast) is not really relevant or useful. It would have to check at runtime anyway, like cast() would, and it would only give very minor (and easily wrong, too restrictive) safety guards by the compiler.

Opinions?

Memory leak

Can't say exactly, but think it is error. For me this introduce memory leak.
Here call to container function

FromGlibContainer::from_glib_container_num(ptr, num)

but functin is from_glib_full_as_vec, so as i understand it must also transfer owning of items. so it must be from_glib_full_num ?

Running into link errors on Windows

After fixing a bunch of configuration-related compiler errors, I was presented with this:

note: C:\users\austin\Rust\gdk\target\debug\deps\libglib-fcaf29643d8f5d21.rlib(glib-fcaf29643d8f5d21.o): In function `glib::permission::Permission::get_allowed':
C:\msys64\home\Austin\.cargo\git\checkouts\glib-27833b4b6d67ca46\master\src/permission.rs:27: undefined reference to `g_permission_get_allowed'
C:\users\austin\Rust\gdk\target\debug\deps\libglib-fcaf29643d8f5d21.rlib(glib-fcaf29643d8f5d21.o): In function `glib::permission::Permission::get_can_acquire':
C:\msys64\home\Austin\.cargo\git\checkouts\glib-27833b4b6d67ca46\master\src/permission.rs:34: undefined reference to `g_permission_get_can_acquire'
C:\users\austin\Rust\gdk\target\debug\deps\libglib-fcaf29643d8f5d21.rlib(glib-fcaf29643d8f5d21.o): In function `glib::permission::Permission::get_can_release':
C:\msys64\home\Austin\.cargo\git\checkouts\glib-27833b4b6d67ca46\master\src/permission.rs:41: undefined reference to `g_permission_get_can_release'
C:\users\austin\Rust\gdk\target\debug\deps\libglib-fcaf29643d8f5d21.rlib(glib-fcaf29643d8f5d21.o): In function `glib::permission::Permission::impl_update':
C:\msys64\home\Austin\.cargo\git\checkouts\glib-27833b4b6d67ca46\master\src/permission.rs:48: undefined reference to `g_permission_impl_update'
C:\users\austin\Rust\gdk\target\debug\deps\libglib-fcaf29643d8f5d21.rlib(glib-fcaf29643d8f5d21.o): In function `glib::value::Value::new':
C:\msys64\home\Austin\.cargo\git\checkouts\glib-27833b4b6d67ca46\master\src/value.rs:36: undefined reference to `create_gvalue'

The g_permission functions are defined by the GIO library, a separate lib and link unit on Windows. And then create_gvalue() is an internal function not exported in the GLib headers, at least for me.

This is with the latest Windows x64 release of GTK from here.

Possible solutions:

  • Move the g_permission functions to a gio-sys crate that links to -lgio-2
  • Use g_value_init() instead of create_gvalue()

unresolved name `gobject_ffi::g_value_set_schar

Hello,
I am trying to compile rrun which uses this library.
When I run cargo build, cargo throws the following errors:

/home/uniaika/.cargo/registry/src/github.com-1ecc6299db9ec823/glib-0.0.4/src/value.rs:69:18: 69:48 error: unresolved name `gobject_ffi::g_value_set_schar` [E0425]
/home/uniaika/.cargo/registry/src/github.com-1ecc6299db9ec823/glib-0.0.4/src/value.rs:69         unsafe { gobject_ffi::g_value_set_schar(&mut self.inner, v_char) }
                                                                                                          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/uniaika/.cargo/registry/src/github.com-1ecc6299db9ec823/glib-0.0.4/src/value.rs:69:18: 69:48 help: run `rustc --explain E0425` to see a detailed explanation
/home/uniaika/.cargo/registry/src/github.com-1ecc6299db9ec823/glib-0.0.4/src/value.rs:74:18: 74:48 error: unresolved name `gobject_ffi::g_value_get_schar` [E0425]
/home/uniaika/.cargo/registry/src/github.com-1ecc6299db9ec823/glib-0.0.4/src/value.rs:74         unsafe { gobject_ffi::g_value_get_schar(&self.inner) }
                                                                                                          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/uniaika/.cargo/registry/src/github.com-1ecc6299db9ec823/glib-0.0.4/src/value.rs:74:18: 74:48 help: run `rustc --explain E0425` to see a detailed explanation

glib::Error's Debug impl is useless

It currently prints the pointer to the GError, but not the actual content of the error. While generally this is fine, for everything implementing std::error::Error this is suboptimal: when observing an error, the standard way of printing it is via the Debug trait (and not Display).

Introspection

Hello.
I wonder if it is possible to do introspection (i.e. getting the type of the Object) because I feel like this code could be written in a better way:

pub fn is_enabled(element: &DOMElement) -> bool {
    let input_element: Result<DOMHTMLInputElement, _> = element.clone().downcast();
    let select_element: Result<DOMHTMLSelectElement, _> = element.clone().downcast();
    let textarea_element: Result<DOMHTMLTextAreaElement, _> = element.clone().downcast();
    if let Ok(element) = input_element {
        !element.get_disabled()
    }
    else if let Ok(element) = select_element {
        !element.get_disabled()
    }
    else if let Ok(element) = textarea_element {
        !element.get_disabled()
    }
    else {
        true
    }
}

Or is there a is_a() method that could be used to avoid these multiple clones and downcasts?
Thanks.

Relicense under dual MIT/Apache-2.0

This issue was automatically generated. Feel free to close without ceremony if
you do not agree with re-licensing or if it is not possible for other reasons.
Respond to @cmr with any questions or concerns, or pop over to
#rust-offtopic on IRC to discuss.

You're receiving this because someone (perhaps the project maintainer)
published a crates.io package with the license as "MIT" xor "Apache-2.0" and
the repository field pointing here.

TL;DR the Rust ecosystem is largely Apache-2.0. Being available under that
license is good for interoperation. The MIT license as an add-on can be nice
for GPLv2 projects to use your code.

Why?

The MIT license requires reproducing countless copies of the same copyright
header with different names in the copyright field, for every MIT library in
use. The Apache license does not have this drawback. However, this is not the
primary motivation for me creating these issues. The Apache license also has
protections from patent trolls and an explicit contribution licensing clause.
However, the Apache license is incompatible with GPLv2. This is why Rust is
dual-licensed as MIT/Apache (the "primary" license being Apache, MIT only for
GPLv2 compat), and doing so would be wise for this project. This also makes
this crate suitable for inclusion and unrestricted sharing in the Rust
standard distribution and other projects using dual MIT/Apache, such as my
personal ulterior motive, the Robigalia project.

Some ask, "Does this really apply to binary redistributions? Does MIT really
require reproducing the whole thing?" I'm not a lawyer, and I can't give legal
advice, but some Google Android apps include open source attributions using
this interpretation. Others also agree with
it
.
But, again, the copyright notice redistribution is not the primary motivation
for the dual-licensing. It's stronger protections to licensees and better
interoperation with the wider Rust ecosystem.

How?

To do this, get explicit approval from each contributor of copyrightable work
(as not all contributions qualify for copyright, due to not being a "creative
work", e.g. a typo fix) and then add the following to your README:

## License

Licensed under either of

 * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
 * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)

at your option.

### Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any
additional terms or conditions.

and in your license headers, if you have them, use the following boilerplate
(based on that used in Rust):

// Copyright 2016 glib Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

It's commonly asked whether license headers are required. I'm not comfortable
making an official recommendation either way, but the Apache license
recommends it in their appendix on how to use the license.

Be sure to add the relevant LICENSE-{MIT,APACHE} files. You can copy these
from the Rust repo for a plain-text
version.

And don't forget to update the license metadata in your Cargo.toml to:

license = "MIT OR Apache-2.0"

I'll be going through projects which agree to be relicensed and have approval
by the necessary contributors and doing this changes, so feel free to leave
the heavy lifting to me!

Contributor checkoff

To agree to relicensing, comment with :

I license past and future contributions under the dual MIT/Apache-2.0 license, allowing licensees to chose either at their option.

Or, if you're a contributor, you can check the box in this repo next to your
name. My scripts will pick this exact phrase up and check your checkbox, but
I'll come through and manually review this issue later as well.

IsA<> trait has to be unsafe

As @alexcrichton noticed yesterday, the IsA<> trait must be unsafe. Otherwise you could safely implement it e.g. impl IsA<gtk::Button> for gtk::Label or similarly silly things.

Making the ToGlibPtr trait unsafe would also solve that, but that one generally seems fine. You can safely convert a gtk::Button to a *mut gtk_ffi::GtkButton, you just can't dereference that pointer safely (but you never could do that anyway).

Add g_signal_handler_block/unblock

Needed for a project I'm working on. Should be simple to implement I think, so I'm willing to do it as I did for signal_stop_emission*().

GKeyFile is missing

GKeyFile is missing from the bindings, so a bit hard to use with Rust.

Should these be auto generated or it supposed to be done by hand?

glib_wrapper!: conflicting implementations of trait `glib::translate::ToGlibPtr<'_, *mut gobject_ffi::GObject>`

See https://github.com/sdroege/gst-plugin-rs/blob/476553d42d2d79fa80f9a70e71d9016e757dc5fe/gst-plugin/src/source.rs#L407-L411

Without specifying the ffi types here, this fails compiling. Specifying them here should be unneeded and I'm not doing that anywhere else (also the [] should be unneeded). Compiler error is the following:

error[E0119]: conflicting implementations of trait `glib::translate::ToGlibPtr<'_, *mut gobject_ffi::GObject>` for type `source::RsSrcWrapper`:
   --> gst-plugin/src/source.rs:406:1
    |
406 |    glib_wrapper! {
    |   _^
    |  |_|
    | ||
407 | ||     pub struct RsSrcWrapper(Object<RsSrc>): [gst_base::BaseSrc,
408 | ||                                              gst::Element,
409 | ||                                              gst::Object,
...   ||
415 | ||     }
416 | || }
    | || ^
    | ||_|
    | |__first implementation here
    |    conflicting implementation for `source::RsSrcWrapper`
    |
    = note: this error originates in a macro outside of the current crate

error[E0119]: conflicting implementations of trait `glib::translate::ToGlibPtr<'_, *mut gobject_ffi::GObject>` for type `source::RsSrcWrapper`:
   --> gst-plugin/src/source.rs:406:1
    |
406 |    glib_wrapper! {
    |   _^
    |  |_|
    | ||
407 | ||     pub struct RsSrcWrapper(Object<RsSrc>): [gst_base::BaseSrc,
408 | ||                                              gst::Element,
409 | ||                                              gst::Object,
...   ||
415 | ||     }
416 | || }
    | || ^
    | ||_|
    | |__first implementation here
    |    conflicting implementation for `source::RsSrcWrapper`
    |
    = note: this error originates in a macro outside of the current crate

error[E0119]: conflicting implementations of trait `glib::translate::ToGlibPtr<'_, *mut gobject_ffi::GObject>` for type `source::RsSrcWrapper`:
   --> gst-plugin/src/source.rs:406:1
    |
406 |    glib_wrapper! {
    |   _^
    |  |_|
    | ||
407 | ||     pub struct RsSrcWrapper(Object<RsSrc>): [gst_base::BaseSrc,
408 | ||                                              gst::Element,
409 | ||                                              gst::Object,
...   ||
415 | ||     }
416 | || }
    | || ^
    | ||_|
    | |__first implementation here
    |    conflicting implementation for `source::RsSrcWrapper`
    |
    = note: this error originates in a macro outside of the current crate

error[E0119]: conflicting implementations of trait `glib::translate::ToGlibPtr<'_, *mut gobject_ffi::GObject>` for type `source::RsSrcWrapper`:
   --> gst-plugin/src/source.rs:406:1
    |
406 |    glib_wrapper! {
    |   _^
    |  |_|
    | ||
407 | ||     pub struct RsSrcWrapper(Object<RsSrc>): [gst_base::BaseSrc,
408 | ||                                              gst::Element,
409 | ||                                              gst::Object,
...   ||
415 | ||     }
416 | || }
    | || ^
    | ||_|
    | |__first implementation here
    |    conflicting implementation for `source::RsSrcWrapper`
    |
    = note: this error originates in a macro outside of the current crate

error: aborting due to 4 previous errors

Note that this error happens once for every class it inherits from, and every interface it implements. This suggests that the problem is in this part of the macro:

glib/src/object.rs

Lines 461 to 483 in d17431e

(@munch_impls $name:ident, $super_name:path) => {
#[doc(hidden)]
impl<'a> $crate::translate::ToGlibPtr<'a,
*mut <$super_name as $crate::wrapper::Wrapper>::GlibType> for $name {
type Storage = <$crate::object::ObjectRef as
$crate::translate::ToGlibPtr<'a, *mut $crate::object::GObject>>::Storage;
#[inline]
fn to_glib_none(&'a self) -> $crate::translate::Stash<'a,
*mut <$super_name as $crate::wrapper::Wrapper>::GlibType, Self> {
let stash = self.0.to_glib_none();
debug_assert!($crate::types::instance_of::<$super_name>(stash.0 as *const _));
$crate::translate::Stash(stash.0 as *mut _, stash.1)
}
#[inline]
fn to_glib_full(&self)
-> *mut <$super_name as $crate::wrapper::Wrapper>::GlibType {
let ptr = self.0.to_glib_full();
debug_assert!($crate::types::instance_of::<$super_name>(ptr as *const _));
ptr as *mut _
}
}

<$super_name as $crate::wrapper::Wrapper>::GlibType> seems to expand to gobject_ffi::GObject for all of them. But there shouldn't even be an implementation like that.

@GuillaumeGomez @EPashkin Any ideas what could be the cause here? :)
Or maybe @federicomenaquintero who currently is going through all this?

Internal compiler error

Hello.
When trying to compile a project depending on gtk (and thus glib), I get the following error:

   Compiling glib v0.0.5
error: internal compiler error: ty_is_local invoked on unexpected type: [type error]
note: the compiler unexpectedly panicked. this is a bug.
note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports
thread 'rustc' panicked at 'Box<Any>', ../src/libsyntax/diagnostic.rs:253
stack backtrace:
   1:     0x7f3415555150 - sys::backtrace::tracing::imp::write::h5b6ace072a698e367Et
   2:     0x7f341555b945 - panicking::log_panic::_<closure>::closure.40164
   3:     0x7f341555b3df - panicking::log_panic::h6d8190bda72bc747Arx
   4:     0x7f3415525323 - sys_common::unwind::begin_unwind_inner::h94eea8313ef59f71cys
   5:     0x7f340f3fc407 - sys_common::unwind::begin_unwind::begin_unwind::h4274098006826536074
   6:     0x7f340f3fd2b6 - diagnostic::_<impl>::bug::h58a7af07988e46b3UNB
   7:     0x7f34132ade33 - session::_<impl>::bug::h213087ebc98070c1s5w
   8:     0x7f34134c6b16 - middle::traits::coherence::ty_is_local_constructor::h75ac300f619dacd4W6R
   9:     0x7f34134c5dab - middle::traits::coherence::ty_is_local::h2152d6a6c9a70efdG5R
  10:     0x7f34134c43d9 - middle::traits::coherence::orphan_check_trait_ref::h83d5c3db56fab02akWR
  11:     0x7f34134e9c92 - middle::traits::select::_<impl>::candidate_from_obligation::h393efaca65f5af5cMuW
  12:     0x7f34134f1e0c - middle::traits::select::_<impl>::evaluate_stack::hf9d672f70e730aff6jW
  13:     0x7f34134f0ebe - middle::traits::select::_<impl>::evaluate_predicate_recursively::heb447c75ffd8fe018aW
  14:     0x7f34134f2145 - middle::traits::select::_<impl>::evaluate_candidate::_<closure>::closure.99512
  15:     0x7f34134f1e8e - middle::traits::select::_<impl>::evaluate_stack::hf9d672f70e730aff6jW
  16:     0x7f34134f0ebe - middle::traits::select::_<impl>::evaluate_predicate_recursively::heb447c75ffd8fe018aW
  17:     0x7f34134c03fb - middle::traits::coherence::overlap::h26b526550e519e4cYDR
  18:     0x7f34134bfcac - middle::traits::coherence::overlapping_impls::hb6802312fbcad60fYBR
  19:     0x7f3414241645 - coherence::overlap::_<impl>::check_if_impls_overlap::h63d63c4df3f6d9b3zYA
  20:     0x7f34140f7c41 - coherence::check_coherence::hd5f57cb933e3799e3UB
  21:     0x7f34140f04c9 - check_crate::h9b4d8810bf169e71PpD
  22:     0x7f3415a4c85d - driver::phase_3_run_analysis_passes::_<closure>::closure.25151
  23:     0x7f3415a303c3 - middle::ty::context::_<impl>::create_and_enter::create_and_enter::h9927264928927630959
  24:     0x7f3415a2b77b - driver::phase_3_run_analysis_passes::h9394773446094229087
  25:     0x7f34159fd662 - driver::compile_input::h1f61a158c52a8220cca
  26:     0x7f34159ef1db - run_compiler::hd87e09e88aee8063zvc
  27:     0x7f34159ec206 - sys_common::unwind::try::try_fn::try_fn::h2507626549812350305
  28:     0x7f3415552de8 - __rust_try
  29:     0x7f341554b24b - sys_common::unwind::try::inner_try::h4958b46263018defKus
  30:     0x7f34159ec554 - boxed::_<impl>::call_box::call_box::h4575607361476731753
  31:     0x7f341555a473 - sys::thread::_<impl>::new::thread_start::h8f57d9485bcbc18flNw
  32:     0x7f340ec4f4a3 - start_thread
  33:     0x7f34151ea13c - clone
  34:                0x0 - <unknown>

Could not compile `glib`.

To learn more, run the command again with --verbose.

I use rustc 1.6.0-nightly (9303055f3 2015-11-19).

Thanks to fix this issue.

Add accessors for raw objects

It would be very useful to provide accessors to the raw pointers to the glib/gtk objects underlying the wrappers added by gtk-rs. This would make it easier to port applications to use parts of gtk-rs while not all needed functionality has been wrapped yet.

GSource closures are inconvenient to use in combination with GTK due to Send

See gtk-rs/gtk#550 with potential solution based on SendCell (implementation linked there).

Because glib::idle_add() and others require Send on the closure (correctly), no GTK objects (which are non-Send) can be used in there. GTK has a workaround by having special gtk::idle_add(), but adding variants for everything else that do this is not scaling.
And it does not solve the problem of actually wanting to pass a GTK object from another thread into the closure, but only use it in the closure (which is valid because it's all from the main thread).

My suggestion would be that we either get something like SendCell into glib, or I could also make it a separate crate and we point people with such problems to that.

SendCell code: https://github.com/sdroege/gstreamer-rs/blob/5676aeb3efaabe263f2c524746032c8441671830/examples/src/bin/gtksink.rs#L126

Will not work on 1.0

Can't build it with beta because of #![feature(alloc)] and they don't plan to make alloc stable in 1.0 either.

Implementation of FromGlibPtrFull for Value is wrong

Hello.
It seems the implementation of FromGlibPtrFull for Value causes an invalid free:
I updated my pull request #173 to use the content of the pull request #172 by @sdroege and it now segfaults.
Here is the output of valgrind:

==10812== Invalid free() / delete / delete[] / realloc()
==10812==    at 0x4C2C14B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10812==    by 0x148D8C: _$LT$glib..value..Value$u20$as$u20$glib..translate..FromGlibPtrFull$LT$$BP$mut$u20$gobject_sys..GValue$GT$$GT$::from_glib_full::h20d87ff77f270988 (value.rs:265)
==10812==    by 0x144D7E: glib::closure::Closure::invoke::h11509ea4ef43c853 (closure.rs:84)
==10812==    by 0x145D99: glib::closure::tests::test_closure::hc4c274cd29409c69 (closure.rs:159)
==10812==    by 0x15C5A1: {{closure}} (lib.rs:1451)
==10812==    by 0x15C5A1: call_once<closure,(())> (ops.rs:2663)
==10812==    by 0x15C5A1: _$LT$F$u20$as$u20$test..FnBox$LT$T$GT$$GT$::call_box::hbc50e286d45b763c (lib.rs:140)
==10812==    by 0x197D4A: __rust_maybe_catch_panic (lib.rs:98)
==10812==    by 0x1507A3: try<(),std::panic::AssertUnwindSafe<closure>> (panicking.rs:433)
==10812==    by 0x1507A3: catch_unwind<std::panic::AssertUnwindSafe<closure>,()> (panic.rs:361)
==10812==    by 0x1507A3: {{closure}} (lib.rs:1390)
==10812==    by 0x1507A3: std::sys_common::backtrace::__rust_begin_short_backtrace::h0399439aaa17b770 (backtrace.rs:136)
==10812==    by 0x151542: {{closure}}<closure,()> (mod.rs:363)
==10812==    by 0x151542: call_once<(),closure> (panic.rs:296)
==10812==    by 0x151542: std::panicking::try::do_call::h0422a104882722ca (panicking.rs:454)
==10812==    by 0x197D4A: __rust_maybe_catch_panic (lib.rs:98)
==10812==    by 0x1573AC: try<(),std::panic::AssertUnwindSafe<closure>> (panicking.rs:433)
==10812==    by 0x1573AC: catch_unwind<std::panic::AssertUnwindSafe<closure>,()> (panic.rs:361)
==10812==    by 0x1573AC: {{closure}}<closure,()> (mod.rs:362)
==10812==    by 0x1573AC: _$LT$F$u20$as$u20$alloc..boxed..FnBox$LT$A$GT$$GT$::call_box::h8e8eb9ac7178c465 (boxed.rs:648)
==10812==    by 0x18FB65: call_once<(),()> (boxed.rs:658)
==10812==    by 0x18FB65: start_thread (thread.rs:21)
==10812==    by 0x18FB65: std::sys::imp::thread::Thread::new::thread_start::h227b2afaa9316a8d (thread.rs:84)
==10812==    by 0x57B02E6: start_thread (in /usr/lib/libpthread-2.25.so)
==10812==  Address 0x71fef40 is on thread 2's stack
==10812==  in frame #2, created by glib::closure::Closure::invoke::h11509ea4ef43c853 (closure.rs:68)
==10812== 

If I remove this line:

glib_ffi::g_free(ptr as *mut c_void);

in the implementation, the test passes.
I think it makes sense to remove this line since Value::unitialized() returns a zeroed struct, so this tries to free a null pointer, right?

Also, there's some unused imports that can be removed.

mismatched types

.cargo/registry/src/github.com-0a35038f75765ae4/glib-0.0.4/src/signal.rs:12:53: 12:61 error: mismatched types:
 expected `*mut gobject_sys::GObject`,
    found `*mut libc::types::common::c95::c_void`
(expected struct `gobject_sys::GObject`,
    found enum `libc::types::common::c95::c_void`) [E0308]
.cargo/registry/src/github.com-0a35038f75765ae4/glib-0.0.4/src/signal.rs:12     let handle = gobject_ffi::g_signal_connect_data(receiver, signal_name.to_glib_none().0,
                                                                                                                                                 ^~~~~~~~
.cargo/registry/src/github.com-0a35038f75765ae4/glib-0.0.4/src/signal.rs:12:53: 12:61 help: run `rustc --explain E0308` to see a detailed explanation
error: aborting due to previous error
Build failed, waiting for other jobs to finish...
Could not compile `glib`.

GResource bindings

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.

non-exhaustive patterns: `Mesh` not covered

I'm getting this error when trying to build glib (I'm trying to do cargo doc for cairo-rs).

   Compiling glib v0.0.3 (https://github.com/gtk-rs/glib#607030ed)
src/patterns.rs:33:5: 42:6 error: non-exhaustive patterns: `Mesh` not covered [E0004]
src/patterns.rs:33     match pattern_type {
src/patterns.rs:34         PatternType::Solid            => Box::new(SolidPattern::wrap(ptr))   as Box<Pattern>,
src/patterns.rs:35         PatternType::Surface          => Box::new(SurfacePattern::wrap(ptr)) as Box<Pattern>,
src/patterns.rs:36         PatternType::LinearGradient   => Box::new(LinearGradient::wrap(ptr)) as Box<Pattern>,
src/patterns.rs:37         PatternType::RadialGradient   => Box::new(RadialGradient::wrap(ptr)) as Box<Pattern>,
src/patterns.rs:38         #[cfg(cairo_1_12)]

Use newtype wrapper around u64 for signal handler ids

I.e. what the connect functions return. These are not arbitrary u64 but have a meaning, and we probably want to prevent people from mixing these with other u64 (or doing arithmetic on them, etc).

Might also make sense to not implement Copy/Clone on them (and the same for SourceId), as you can only really disconnect a signal handler once.

DerefMut on TypedValue is unsafe

let mut meh: TypedValue<i32> = (&123i32).into();
let meh2: Value = (&1u8).to_value();
*meh = meh2;

And suddenly we have a TypedValue<i32> that actually contains an u8.

Logging functions (e.g. g_debug)

Bindings for g_log() and its derivatives (g_debug(), g_warning(), ...) are still missing.

One can of course use Rust's print!() macro's, but that means either manually parsing the G_DEBUG variable or the similar options like --g-debug, or ignoring them.

Splitting out gio

I'm thinking of creating a gio crate to avoid some workarounds and special-casing. Most of the G* object hierarchy (e.g. GApplication, GMenu) lives in gio. Generating them will be more straightforward if they have their own crate.

There's an additional wrapper complication that needs to be introduced. Turns out I've pushed convenience of declarations too far and coherence prevents cross-crate inheritance now. This can't work:

glib_wrapper! {
    pub struct Application(Object<ffi::GtkApplication>): glib::Application;
...

A more extended version would look like this:

glib_wrapper! {
    pub struct Application(Object<ffi::GtkApplication>): [glib::Application => gio_sys::GApplication];

The confusing discrepancy between glib and gio is apparent here.

Wrapper has GlibType as associated type; also having the Class would be useful

I'm working on gnome-class, the code generator for gobject implementations in Rust.

If I have Gtk::Widget, I can conveniently obtain the type of the ffi struct that is wrapped (gtk_ffi::GtkWidget) by writing

<Gtk::Widget as glib::wrapper::Wrapper>::GlibType

However, I would like to be able to get to ffi:GtkWidgetClass as well. This is so that the gobject implementation can access parent_class.finalize(), for example.

Right now we have

        impl $crate::wrapper::Wrapper for $name {
            type GlibType = $ffi_name;
        }

inside the macro glib_object_wrapper!(). Could we also have a "type GlibClassType = $ffi_class_name" in the Wrapper trait?

This leads to the question of how to obtain that. I think we may need to modify glib_wrapper!() so that it can be called as

glib_wrapper! {
    pub struct Widget(Object<ffi::GtkWidget, ffi::GtkWidgetClass>): Buildable;

    match fn {
        get_type => || ffi::gtk_widget_get_type(),
    }
}

i.e. with an extra "argument" inside the Object<>.

This is obviously an API break. I'm open to ideas :)

GTypeInterfaces are not in the binding

Some places in the documentation mention interfaces, for example this bit in the docs for IsA<>

/// For instance, since originally `GtkWidget` is a subclass of `GObject` and
/// implements the `GtkBuildable` interface, `gtk::Widget` implements
/// `IsA<glib::Object>` and `IsA<gtk::Buildable>`.

I was looking at where the IsA trait is implemented for the various object types. Let's look at the docs for the macro that generates it...

/// glib_wrapper! {
///     /// A container with just one child.
///     pub struct Bin(Object<ffi::GtkBin>): Container, Widget, Buildable;

But in the actual bin.rs there is only this:

glib_wrapper! {
    pub struct Bin(Object<ffi::GtkBin>): Container, Widget;

Also, GtkWidget supports Buildable and AtkImplementor (see here), but they are not listed in gtk/src/auto/widget.rs.

Some other interfaces are declared just fine, however. For example, recent_chooser_widget.rs properly declares Orientable (because of Box), and the RecentChooser iface.

Also, I'm not sure how glib-rs handles calling an interface method on an instance. For example, GTK+ has this code:

void
gtk_recent_chooser_set_sort_func  (GtkRecentChooser  *chooser,
				   GtkRecentSortFunc  sort_func,
				   gpointer           sort_data,
				   GDestroyNotify     data_destroy)
{
  g_return_if_fail (GTK_IS_RECENT_CHOOSER (chooser));
  
  GTK_RECENT_CHOOSER_GET_IFACE (chooser)->set_sort_func (chooser,
  							 sort_func,
  							 sort_data,
  							 data_destroy);
}

That GTK_RECENT_CHOOSER_GET_IFACE() expands to a call to g_type_interface_peek(), which returns NULL if the instance is not of a class that supports that interface. I can't find any calls to g_type_interface_peek() in glib-rs at all :)

Add getting the error message from a GError

I don't think there's a way to get the message from a GError in safe code right now. I need to add this and add a Debug implementation for glib::Error so I can use it in a Result.

I can implement a message() -> &str function to access the field, if that's all that needs to be done.

Have glib_object_wrapper! generate a get_class() method

From here - @sdroege suggests that it would be nice to have glib_object_wrapper!() generate

#[repr(C)]
pub struct FooClass(ffi::BarFooClass);

impl IsA<ParentOfFooClass> for FooClass { }
impl IsA<ParentOfParentParentOfFooClass> for FooClass { }

impl Foo {
    pub fn get_class(&self) -> &FooClass {
        unsafe {
            let stash = self.to_glib_none();
            let ptr: ffi::Foo = stash.0;
            let class = *(ptr as *const *const ffi::BarFooClass);
            &*(class as *const FooClass)
        }
}

To generate the FooClass identifier, we either need the concat_idents!() macro, which is a nightly-only feature, or a procedural macro inside glib-rs that generates such an identifier.

make glib::Error Send/Sync?

Otherwise it seems rather incompatible with error_chain crate.

I get e.g.:

error[E0277]: the trait bound `*mut glib_sys::GError: std::marker::Send` is not satisfied in `errors::Error`
  --> src/errors.rs:9:1
   |
9  | / error_chain! {
10 | |     foreign_links {
11 | |         Alsa(alsa::Error);
12 | |         IO(std::io::Error);
...  |
15 | |     }
16 | | }
   | |_^ `*mut glib_sys::GError` cannot be sent between threads safely
   |
   = help: within `errors::Error`, the trait `std::marker::Send` is not implemented for `*mut glib_sys::GError`
   = note: required because it appears within the type `glib::boxed::AnyBox<glib_sys::GError>`
   = note: required because it appears within the type `glib::boxed::Boxed<glib_sys::GError, glib::error::MemoryManager>`
   = note: required because it appears within the type `glib::Error`
   = note: required because it appears within the type `errors::ErrorKind`
   = note: required because it appears within the type `errors::Error`
   = note: required by `error_chain::ChainedError`
   = note: this error originates in a macro outside of the current crate

error[E0277]: the trait bound `*mut i8: std::marker::Send` is not satisfied in `glib_sys::GError`
  --> src/errors.rs:9:1
   |
9  | / error_chain! {
10 | |     foreign_links {
11 | |         Alsa(alsa::Error);
12 | |         IO(std::io::Error);
...  |
15 | |     }
16 | | }
   | |_^ `*mut i8` cannot be sent between threads safely
   |
   = help: within `glib_sys::GError`, the trait `std::marker::Send` is not implemented for `*mut i8`
   = note: required because it appears within the type `glib_sys::GError`
   = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<glib_sys::GError>`
   = note: required because it appears within the type `std::boxed::Box<glib_sys::GError>`
   = note: required because it appears within the type `glib::boxed::AnyBox<glib_sys::GError>`
   = note: required because it appears within the type `glib::boxed::Boxed<glib_sys::GError, glib::error::MemoryManager>`
   = note: required because it appears within the type `glib::Error`
   = note: required because it appears within the type `errors::ErrorKind`
   = note: required because it appears within the type `errors::Error`
   = note: required by `error_chain::ChainedError`
   = note: this error originates in a macro outside of the current crate

Custom Glib signals in user-defined structs

Is there any way I could implement mainloop-aware signal for my struct? In glibmm there is sigc which is pretty awesome since it allows to define statically typed signals. In python bindings I could set "gsignals" property. How could I define signals in rust bindings?

Closure::emit() / ObjectExit::emit() could use stack allocated array instead of Vec

let mut values: Vec<_> = values.iter()

let mut c_args: Vec<gobject_ffi::GValue> = Vec::new();

It would make sense to use a stack allocated array here for < N parameters to make things more efficient and not have that many allocations per call. N = 10 for example would be sufficient already for 99% of the cases, and only uses up 10*(8+8+8) == 240 bytes of stack memory.

GValue can be used to violate Send/Sync traits

E.g. you can store a gtk::Widget in a GValue and then send it to another thread. GValue is (and should be) Send, but it's content might not be.

A solution might be to have two kinds of Value, one Send and one not. And being able to transform from the Send one to the other, similar to TypedValue.

Use ToValue trait for ObjectExt::set_property()

glib/src/object.rs

Lines 562 to 564 in ba748d1

fn set_property<'a, N: Into<&'a str>>(&self, property_name: N, value: &Value) -> Result<(), BoolError>;
fn get_property<'a, N: Into<&'a str>>(&self, property_name: N) -> Result<Value, BoolError>;
fn has_property<'a, N: Into<&'a str>>(&self, property_name: N, type_: Option<Type>) -> Result<(), BoolError>;

Either as trait objects (which fortunately work for ToValue), or generics. Neither doesn't really make a difference, for you to decide.

Could also use ToValue for ::emit() at least, but as this is more of a plumbing function it is maybe not too useful. And for ::connect() we can't do it anyway, so maybe let's keep the symmetry there.

Comments?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.