Giter Club home page Giter Club logo

gio's Introduction

gtk3-rs CI

This project is UNMAINTAINED. Please take a look at gtk4-rs instead!

The gtk-rs organization aims to provide safe Rust binding over GObject-based libraries. You can find more about it on https://gtk-rs.org.

This repository contains all the "core" crates of the gtk-rs organization. For more information about each crate, please refer to their README.md file in their directory.

Minimum supported Rust version

Currently, the minimum supported Rust version is 1.70.0.

Documentation

Ecosystem

The gtk3-rs repository contains Rust crates for GTK 3. However there is a large ecosystem of GObject libraries and many of these libraries have Rust bindings based on the tooling included in gtk-rs. Of particular note:

  • gtk-rs-core - bindings for some of the core libraries such as glib, gio, pango, graphene
  • gstreamer-rs - bindings for the GStreamer media framework

Additionally, Rust bindings for various libraries are hosted on GNOME's GitLab instance and can be found at https://gitlab.gnome.org/World/Rust.

When using crates that are not part of the gtk-rs repository, you will need to be careful and ensure that they do not pull in incompatible versions of core crates like glib-rs.

Regenerating

To regenerate crates using gir, please use the generator.py file as follows:

$ python3 generator.py

If you didn't do so yet, please check out all the submodules before via

$ git submodule update --checkout

Development

This repository is mostly split into two branches: master and crate. master contains the not yet released code and is where new developments are happening. crate contains the last release source code and isn't supposed to be updated.

This repository is structured as follows:

- crate/
   |
   |-- README.md
   |-- Gir.toml
   |-- Cargo.toml
   |-- src/
   |-- sys/

The crate is a "top" directory (so "atk" or "gdk" in here for example). Each crate contains:

  • README.md: explanations about the crate itself and eventually some details.
  • Cargo.toml: descriptor of the crate, used by cargo and Rust.
  • Gir.toml: configuration used by gir to generate most of the crates' code.
  • src: the source code of the crate.
  • sys: the 1:1 bindings of the C API.

The gir and gir-files top folders are not crates, but are git submodules which respectively contain the gir tool and the gir files used by the generator.

When running generator.py the tool will automatically update these git submodules and run the gir tool on the gir files to regenerate the code.

During development, it is useful to execute the generator with a different version of the gir tool or of the gir files, for instance to test if the code generation is successful before submitting a pull request to update one of the submodules. This can be done by specifying arguments to the generator script, for instance, to run the generator on a local copy of the gir files:

$ python3 generator.py --gir-files-directory ../gir-files/

See python3 generator.py --help for more details.

gio's People

Contributors

7r3nzy avatar antoyo avatar bilelmoussaoui avatar cogitri avatar dns2utf8 avatar dvhaeren avatar epashkin avatar federicomenaquintero avatar fengalin avatar fkrull avatar gkoz avatar guillaumegomez avatar hfiguiere avatar kinnison avatar mathieuduponchelle avatar moggiesir avatar nielsdg avatar philn avatar sdroege avatar sophie-h avatar tmiasko avatar valpackett avatar ystreet 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

Watchers

 avatar  avatar  avatar  avatar  avatar

gio's Issues

No TlsBackend?

I'm porting the gstreamer's android initialization code to rust as a learning project. The gstreamer-rs' appsink example works now. The only task left is gst_android_load_gio_module。For that I need the following four functions:

  • gst_android_load_gio_module
  • g_tls_backend_get_default
  • g_tls_file_database_new
  • g_tls_backend_set_default_database

I can find gio::TlsDatabase, gio::TlsFileDatabase, but no gio::TlsBackend. I think I should not use gio-sys directly. Could you suggest how I implement gst_android_load_gio_module or gio::TlsBackend in rust?

Followed is the code to be ported to rust:

void
gst_android_load_gio_modules (void)
{
  GTlsBackend *backend;
  const gchar *ca_certs;

  @G_IO_MODULES_LOAD@

  ca_certs = g_getenv ("CA_CERTIFICATES");

  backend = g_tls_backend_get_default ();
  if (backend && ca_certs) {
    GTlsDatabase *db;
    GError *error = NULL;

    db = g_tls_file_database_new (ca_certs, &error);
    if (db) {
      g_tls_backend_set_default_database (backend, db);
      g_object_unref (db);
    } else {
      g_warning ("Failed to create a database from file: %s",
          error ? error->message : "Unknown");
    }
  }
}

Async tests stalls

Sometimes gio test stalls
https://travis-ci.org/gtk-rs/gio/builds/348980232

Tried to add delay in spawned thread but it don't helps.

diff --git a/src/test_util.rs b/src/test_util.rs
index 660e6c0..40a7380 100644
--- a/src/test_util.rs
+++ b/src/test_util.rs
@@ -4,6 +4,7 @@
 
 
 use std::sync::mpsc::{channel, Sender};
+use std::time::Duration;
 use std::thread;
 use glib::*;
 
@@ -16,6 +17,7 @@ pub fn run_async<T: Send + 'static, Q: FnOnce(Sender<T>, MainLoop) + Send + 'sta
     let (tx, rx) = channel();
 
     thread::spawn(move || {
+        thread::sleep(Duration::from_millis(100));
         c.invoke(move || {
             start(tx, l_clone);
         });

Wrong mutability in UnixMountPoint

See e.g.

warning: methods called `is_*` usually take self by reference or no self; consider choosing a less ambiguous name
  --> src/auto/unix_mount_point.rs:98:24
   |
98 |     pub fn is_loopback(&mut self) -> bool {
   |                        ^^^^^^^^^
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#wrong_self_convention

warning: methods called `is_*` usually take self by reference or no self; consider choosing a less ambiguous name
   --> src/auto/unix_mount_point.rs:106:24
    |
106 |     pub fn is_readonly(&mut self) -> bool {
    |                        ^^^^^^^^^
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#wrong_self_convention

warning: methods called `is_*` usually take self by reference or no self; consider choosing a less ambiguous name
   --> src/auto/unix_mount_point.rs:114:30
    |
114 |     pub fn is_user_mountable(&mut self) -> bool {
    |                              ^^^^^^^^^
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#wrong_self_convention

All those getters (and all the other get_() functions at least) should take an immutable reference.

CC @EPashkin Does this need changes in gir, in the gir files, ...?

Should connect_startup take FnOnce instead of Fn?

Say you load some information that will be used in the rendering of your window. You want to pass it into your application init so it can eventually be used in the drawing handler to govern what gets drawn:

fn main() {
    let info = load_info();
    /// ...
    application.connect_startup(move |app| {
        build_ui(app, info);
    };
}

fn build_ui(app: &Application, info: DrawingInfo) {
    // ...
    drawing_area.connect_draw(move |w: &DrawingArea, ctx: &cairo:Context| {
        do_drawing(&info);
    });
}

Now you have a problem because you can't move info out of the connect_startup() closure, because Rust thinks the startup closure may be called multiple times. You could try passing a reference to info to build_ui instead, but then you get lifetime issues because connect_draw wants reference members in the closure to have static lifetime.

I don't see a way around this without either needlessly putting info in an Rc, or cloning it (but then it will forever live in the connect_startup closure even though it's only used once).

Put in another perspective, if the connect_startup() closure is large then it will use a lot of memory for the entire running time of the program, even though it is only called once (right?). So, I'm thinking, shouldn't connect_startup take an FnOnce instead of Fn? That would allow objects to be moved out of the connect_startup closure and the code above would work.

The same goes for other event handlers that are only called once.

SimpleAction parameter type issue

I'm trying this:

    let sub_action = gio::SimpleAction::new_stateful("sub", Some(&"s".to_variant()), &"".to_variant());

But I get this error. Is that a typo? There's no such VariantTy in gio...

  --> src/bin/menu_bar_system.rs:90:22
   |
90 |     let sub_action = gio::SimpleAction::new_stateful("sub", Some(&"s".to_variant()), &"".to_variant());
   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<std::option::Option<&glib::variant::Variant>>` is not implemented for `std::option::Option<&glib::variant_type::VariantTy>`
   |

Build Error on armv7l (RasperryPI): `glib::translate::ToGlibPtr<'_, *mut i8>` is not implemented for `std::path::Path`

Hi there,

I am trying to build https://github.com/centricular/gstwebrtc-demos/tree/master/sendrecv/gst-rust on a raspberry pi armv7l and just ran in the following error which i did not get on x86_64.

cargo build

Compiling gio v0.4.0 (https://github.com/gtk-rs/gio#b95e3d5d)
error[E0277]: the trait bound `std::path::Path: glib::translate::ToGlibPtr<'_, *mut i8>` is not satisfied
  --> /home/pi/.cargo/git/checkouts/gio-a4b825b310a073b9/b95e3d5/src/unix_socket_address.rs:56:37
   |
56 |                 Path(path) => (path.to_glib_none().0, path.as_os_str().len()),
   |                                     ^^^^^^^^^^^^ the trait `glib::translate::ToGlibPtr<'_, *mut i8>` is not implemented for 
`std::path::Path`
   |
   = help: the following implementations were found:
             <std::path::Path as glib::translate::ToGlibPtr<'a, *const u8>>
             <std::path::Path as glib::translate::ToGlibPtr<'a, *mut u8>>

error[E0308]: mismatched types
  --> /home/pi/.cargo/git/checkouts/gio-a4b825b310a073b9/b95e3d5/src/unix_socket_address.rs:61:84
   |
61 |             SocketAddress::from_glib_full(ffi::g_unix_socket_address_new_with_type(path, len as i32, type_.to_glib()))
   |                                                                                    ^^^^ expected u8, found i8
   |
   = note: expected type `*mut u8`
              found type `*mut i8`

error: aborting due to 2 previous errors

Some errors occurred: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.
error: Could not compile `gio`.

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

I built the gio library with gstreamers cerbero installation (both on armv7l and x86_64) and pkg-config --modversion gio-2.0 returns version 2.56.1 on both machines.

Manual bindings for functions with Cancellable args are inconsistent

For functions which take a Cancellable, auto-generated code looks like this:

fn foo<P: IsA<Cancellable>>(cancellable: Option<&P>) { ... }

But in some places in the manually-written bindings, there is this instead:

fn bar(cancellable: Option<&Cancellable>) { ... }

The following are the inconsistent ones I could find in gio:

PollableOutputStreamExtManual
  create_source
  create_source_future
  create_source_stream

InputStreamExtManual
  read
  read_all
  read_all_async
  read_async
  
Subprocess
  communicate_utf8_async
  

impl<F, O, T: 'static, E: 'static> GioFuture<F, O, T, E>
where
    O: Clone + 'static,
    F: FnOnce(&O, oneshot::Sender<Result<T, E>>) -> Cancellable + 'static,
    not sure if it makes sense to let the operation return an IsA<Cancellable> here

    same for impl<F, O, T, E> Future for GioFuture<F, O, T, E>

SocketListenerExtManual
  accept_socket_async
  
SocketExtManual
  receive
  receive_from
  receive_with_blocking
  send
  send_to
  send_with_blocking
  create_source
  create_source_future
  create_source_stream

PollableInputStreamExtManual
  create_source
  create_source_future
  create_source_stream
  read_nonblocking
  
OutputStreamExtManual
  write_async
  write_all
  write_all_async
  
FileExtManual
  replace_contents_async

Unable to write bytes to IOStream using futures

I'm trying to implement a function that'll handle sending out and receiving data from a server I've written. To do so, I'm using SocketClient's connect_to_host_async_future and OutputStream's write_all_async_future functions. What I'm seeing is that the program is able to connect to the server, but immediately fails when trying to write anything to it. The code that I have so far looks like this:

pub fn send_request(request: RequestBuilder) {
    let c = glib::MainContext::default();
    let l = glib::MainLoop::new(Some(&c), false);

    c.push_thread_default();

    let l_clone = l.clone();

    let client = gio::SocketClient::new();
    client.set_timeout(10);

    let req = request.build();

    c.spawn_local(
        client.connect_to_host_async_future(&request.get_host(), 80)
            .map_err(|_| {
                println!("Connection failed");
            })
            .and_then(|(s, conn)| {
                println!("Is connected: {}", &conn.is_connected());
                let stream: IOStream = conn.upcast();
                println!("Stream is closed: {}", &stream.is_closed());
                let writer = stream.get_output_stream().expect("Failed to obtain output stream");

                writer.write_all_async_future(req.into_bytes(), glib::PRIORITY_DEFAULT)
                    .map_err(|(strm, (buf, err))| {
                        println!("Write failed: {}", err);
                        dbg!(strm.is_closed());
                    })
                    .and_then(|(_strm, (buf, count, err))| {
                        dbg!(count);
                        Ok(())
                    })
            })
            .then(move |_| {
                println!("Done with connection");
                l_clone.quit();
                Ok(())
            })
    );

    println!("Going to run");

    l.run();

    println!("Ran");

    c.pop_thread_default();
}

which will output the following:

Going to run
Is connected: true
Stream is closed: false
Write failed: Stream is already closed
[src\net\mod.rs:44] strm.is_closed() = true
Done with connection
Ran

How is the stream closed if it was just previously opened before writing to it? From what I can tell, the stream closes after the "write failed" output message (if I insert a thread::sleep before there, the server won't show a disconnect message until after that sleep period).

How to convert Vec<GString> into Vec<String>

Hello,

I have tried to port Fractal to use new gtk-rs, but I hit by the following problem.

// gio::ProxyResolver can't be sent or shared
thread_local! {
    static PROXY_RESOLVER: gio::ProxyResolver =
        gio::ProxyResolver::get_default().expect("Couldn't get proxy resolver");
}
[]
let http_proxy = PROXY_RESOLVER.with(|resolver| resolver.lookup("http://", None))?;

and then passes to function which accepts Vec<String>. In latest gtk-rs release it changed to return Vec<GString>. So I have tried to do something like .iter().map(|r| r.to_string()), but I am getting something like:

error[E0283]: type annotations required: cannot resolve `_: glib::object::IsA<gio::auto::cancellable::Cancellable>`

And I can't get it done =(

Help is much appreciated.

ThreadedSocketService panics while accepting connection

I'm learning to use gio. And below is my code

use glib::MainContext;
use glib::MainLoop;
use gio::ThreadedSocketService;
use gio::prelude::*;

fn main() {
    let mainloop = MainLoop::new(Some(&MainContext::default()),false);

    let service  = ThreadedSocketService::new(-1);

    if let Err(err) = service.add_inet_port::<glib::Object>(32321, None) {
        return;
    }
    println!("listen 32321");

    service.connect_run(move |_,c,_|->bool{
        println!("{:?}",c);
        return false;
    });

    mainloop.run();
}

When ThreadedSocketService receives a connection, it panics.

   Compiling gtk v0.1.0 (/home/wiky/temp/rust/gtk)
warning: unused variable: `err`
  --> src/main.rs:11:16
   |
11 |     if let Err(err) = service.add_inet_port::<glib::Object>(32321, None) {
   |                ^^^ help: consider prefixing with an underscore: `_err`
   |
   = note: `#[warn(unused_variables)]` on by default

    Finished dev [unoptimized + debuginfo] target(s) in 1.67s
     Running `target/debug/gtk`
listen 32321

connection established

thread '<unnamed>' panicked at 'assertion failed: crate::types::instance_of::<Self>(ptr as *const _)', <::std::macros::panic macros>:2:4
stack backtrace:
   0:     0x55d6a79929f4 - backtrace::backtrace::libunwind::trace::h5d52ba5f20882f09
                               at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.44/src/backtrace/libunwind.rs:86
   1:     0x55d6a79929f4 - backtrace::backtrace::trace_unsynchronized::hceee092869668a74
                               at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.44/src/backtrace/mod.rs:66
   2:     0x55d6a79929f4 - std::sys_common::backtrace::_print_fmt::ha312c2904605e4d5
                               at src/libstd/sys_common/backtrace.rs:78
   3:     0x55d6a79929f4 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h5b9981092140b727
                               at src/libstd/sys_common/backtrace.rs:59
   4:     0x55d6a79ab7fc - core::fmt::write::h5f6d7d8de88b4173
                               at src/libcore/fmt/mod.rs:1063
   5:     0x55d6a7990f33 - std::io::Write::write_fmt::h893169117de3cc15
                               at src/libstd/io/mod.rs:1426
   6:     0x55d6a7994fa5 - std::sys_common::backtrace::_print::h8ab61d4120f7a335
                               at src/libstd/sys_common/backtrace.rs:62
   7:     0x55d6a7994fa5 - std::sys_common::backtrace::print::h8aae19fbb153bf2a
                               at src/libstd/sys_common/backtrace.rs:49
   8:     0x55d6a7994fa5 - std::panicking::default_hook::{{closure}}::h1ee5b7d8b6f83429
                               at src/libstd/panicking.rs:204
   9:     0x55d6a7994cf2 - std::panicking::default_hook::hd6c32c13403f9210
                               at src/libstd/panicking.rs:224
  10:     0x55d6a7995562 - std::panicking::rust_panic_with_hook::h1f2449d529a25f22
                               at src/libstd/panicking.rs:470
  11:     0x55d6a798b441 - std::panicking::begin_panic::h5a36cc3b26b56542
                               at /rustc/8d69840ab92ea7f4d323420088dd8c9775f180cd/src/libstd/panicking.rs:397
  12:     0x55d6a798540a - <glib::object::Object as glib::translate::FromGlibPtrBorrow<*mut gobject_sys::GObject>>::from_glib_borrow::hfc80280ad2f153ca
                               at /home/wiky/.cargo/registry/src/github.com-1ecc6299db9ec823/gio-0.8.1/<::std::macros::panic macros>:2
  13:     0x55d6a79849ee - glib::translate::from_glib_borrow::h80f9642bc3606747
                               at /home/wiky/.cargo/registry/src/github.com-1ecc6299db9ec823/glib-0.9.3/src/translate.rs:1228
  14:     0x55d6a7983498 - <O as gio::auto::threaded_socket_service::ThreadedSocketServiceExt>::connect_run::run_trampoline::hb9b61c2da889377e
                               at /home/wiky/.cargo/registry/src/github.com-1ecc6299db9ec823/gio-0.8.1/src/auto/threaded_socket_service.rs:87
  15:     0x7f6b126f53b7 - <unknown>
  16:     0x7f6b12625a56 - <unknown>
  17:     0x7f6b12643dd1 - g_signal_emit_valist
  18:     0x7f6b126450d3 - g_signal_emit
  19:     0x7f6b12729e39 - <unknown>
  20:     0x7f6b125641d4 - <unknown>
  21:     0x7f6b12563931 - <unknown>
  22:     0x7f6b124c8609 - start_thread
  23:     0x7f6b123d2103 - __clone
  24:                0x0 - <unknown>
fatal runtime error: failed to initiate panic, error 5
Aborted (core dumped)

Bind GIOChannel

Would be nice to have proper GIOChannel bindings at some point.

Idea for "magical" strings

An idea that could (I don't think we should provide it into the bindings directly!) be implemented is as follows:

Currently we are using a wrapper to provide "magical" strings to gio (and in other places as well) such as:

add_action("app.quit", None)

Instead of "app.quit", we could have for instance:

enum Kinds {
    App(Kind),
    System(kind),
    Nothing(Kind),
    // ...
}

enum Kind {
    Quit,
    // ...
}

And then we'd implement ToString and FromString for them. And to make their usage better/easier, we could change the add_action argument take AsRef<str> instead of &str.

I think it could be an interesting idea. Not sure what it'll evolve into... To be discussed! :)

Compilation errors

error[E0277]: the trait bound `std::string::String: glib::translate::ToGlibPtr<'_, *mut i8>` is not satisfied
  --> /home/chessnokov/.cargo/registry/src/github.com-1ecc6299db9ec823/gio-0.5.0/src/subprocess.rs:40:35
   |
40 |         let stdin_buf = stdin_buf.to_glib_full();
   |                                   ^^^^^^^^^^^^ the trait `glib::translate::ToGlibPtr<'_, *mut i8>` is not implemented for `std::string::String`
   |
   = help: the following implementations were found:
             <std::string::String as glib::translate::ToGlibPtr<'a, *const u8>>
             <std::string::String as glib::translate::ToGlibPtr<'a, *mut u8>>
   = note: required because of the requirements on the impl of `glib::translate::ToGlibPtr<'_, *mut i8>` for `std::option::Option<std::string::String>`

error[E0308]: mismatched types
  --> /home/chessnokov/.cargo/registry/src/github.com-1ecc6299db9ec823/gio-0.5.0/src/subprocess.rs:57:77
   |
57 |             ffi::g_subprocess_communicate_utf8_async(self.to_glib_none().0, stdin_buf, cancellable.0, Some(callback), Box::into_raw(user_data) as *mut _);
   |                                                                             ^^^^^^^^^ expected u8, found i8
   |
   = note: expected type `*const u8`
              found type `*mut i8`

error: aborting due to 2 previous errors

Some errors occurred: E0277, E0308.

Build of new SettingsSchemaKey API fails

https://travis-ci.org/sdroege/gstreamer-rs/jobs/309075030#L1030-L1041

error[E0425]: cannot find function `g_settings_schema_key_ref` in module `ffi`

  --> /home/travis/.cargo/git/checkouts/gio-a4b825b310a073b9/c704556/src/auto/settings_schema_key.rs:17:27

   |

17 |         ref => |ptr| ffi::g_settings_schema_key_ref(ptr),

   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^ did you mean `g_settings_schema_ref`?

error[E0425]: cannot find function `g_settings_schema_key_unref` in module `ffi`

  --> /home/travis/.cargo/git/checkouts/gio-a4b825b310a073b9/c704556/src/auto/settings_schema_key.rs:18:29

   |

18 |         unref => |ptr| ffi::g_settings_schema_key_unref(ptr),

   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ did you mean `g_settings_schema_unref`?

cc @EPashkin

SocketListener::accept_async panics

Hi.
The current SocketListener::accept_async method does not work because the Object parameter of the callback should be optional (and the .gir file says so) but it is not.
It might be because gir does not look at the optional attribute when generating the callback.

DataInputStream::read_until_async asserts when empty

This code (using gio = "0.8.0, glib = "0.9.1") reads a line from stdin asynchronously, echos it back out, then exits:

use gio::prelude::*;

fn main() {
    let mainloop = glib::MainLoop::new(None, true);
    let input = unsafe {
        struct RawFdWrap(i32);

        impl std::os::unix::io::IntoRawFd for RawFdWrap {
            fn into_raw_fd(self) -> std::os::unix::io::RawFd {
                self.0 as _
            }
        }

        gio::UnixInputStream::new(RawFdWrap(0))
    };

    let input = gio::DataInputStream::new(&input);

    {
        let mainloop = mainloop.clone();
        input.read_until_async(
            "\n",
            glib::PRIORITY_DEFAULT,
            gio::NONE_CANCELLABLE,
            move |res| {
                println!("{}", res.unwrap().0);
                mainloop.quit();
            },
        );
    }

    mainloop.run();
}

But it asserts when it reads an empty line or an immediate EOF:

thread 'main' panicked at 'assertion failed: !ptr.is_null()', /home/jan/.cargo/registry/src/github.com-1ecc6299db9ec823/glib-0.9.1/src/gstring.rs:35:9
stack backtrace:
   0:     0x55784c7381a4 - backtrace::backtrace::libunwind::trace::h65597d255cb1398b
                               at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/libunwind.rs:88
   1:     0x55784c7381a4 - backtrace::backtrace::trace_unsynchronized::hd4f479d7150ec4a0
                               at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/mod.rs:66
   2:     0x55784c7381a4 - std::sys_common::backtrace::_print_fmt::h015072984a2b172c
                               at src/libstd/sys_common/backtrace.rs:77
   3:     0x55784c7381a4 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h6df05d3335f32194
                               at src/libstd/sys_common/backtrace.rs:61
   4:     0x55784c7509ac - core::fmt::write::h1f444f4312eb6c27
                               at src/libcore/fmt/mod.rs:1028
   5:     0x55784c736a47 - std::io::Write::write_fmt::h8d147888220078ef
                               at src/libstd/io/mod.rs:1412
   6:     0x55784c73a4be - std::sys_common::backtrace::_print::h8a6df0fa81d6af62
                               at src/libstd/sys_common/backtrace.rs:65
   7:     0x55784c73a4be - std::sys_common::backtrace::print::h6f05b4733407e509
                               at src/libstd/sys_common/backtrace.rs:50
   8:     0x55784c73a4be - std::panicking::default_hook::{{closure}}::h0d0a23bd02315dd8
                               at src/libstd/panicking.rs:188
   9:     0x55784c73a1b1 - std::panicking::default_hook::h8d15a9aecb4efac6
                               at src/libstd/panicking.rs:205
  10:     0x55784c73ab0b - std::panicking::rust_panic_with_hook::hbe174577402a475d
                               at src/libstd/panicking.rs:464
  11:     0x55784c732423 - std::panicking::begin_panic::ha904792d2b03cbc9
                               at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/panicking.rs:400
  12:     0x55784c73065f - glib::gstring::GString::new::ha51bbcc739583cae
                               at /home/jan/.cargo/registry/src/github.com-1ecc6299db9ec823/glib-0.9.1/src/gstring.rs:35
  13:     0x55784c7306fc - <glib::gstring::GString as glib::translate::FromGlibPtrFull<*mut i8>>::from_glib_full::hdcd48933a5a36413
                               at /home/jan/.cargo/registry/src/github.com-1ecc6299db9ec823/glib-0.9.1/src/gstring.rs:290
  14:     0x55784c72fbbb - glib::translate::from_glib_full::hde6253237b3c3fcc
                               at /home/jan/.cargo/registry/src/github.com-1ecc6299db9ec823/glib-0.9.1/src/translate.rs:1221
  15:     0x55784c72d8f2 - <O as gio::auto::data_input_stream::DataInputStreamExt>::read_until_async::read_until_async_trampoline::hbcc619cc827bbcc9
                               at /home/jan/.cargo/registry/src/github.com-1ecc6299db9ec823/gio-0.8.0/src/auto/data_input_stream.rs:419
  16:     0x7f3260d8cdc4 - <unknown>
  17:     0x7f3260d927a7 - <unknown>
  18:     0x7f3260dec45a - <unknown>
  19:     0x7f3260dec886 - <unknown>
  20:     0x7f3260df8294 - <unknown>
  21:     0x7f3260d8cdc4 - <unknown>
  22:     0x7f3260d927a7 - <unknown>
  23:     0x7f3260df81b9 - <unknown>
  24:     0x7f3260dc5e8c - <unknown>
  25:     0x7f3260d8cdc4 - <unknown>
  26:     0x7f3260d927a7 - <unknown>
  27:     0x7f3260dc9714 - <unknown>
  28:     0x7f3260dc9799 - <unknown>
  29:     0x7f3260bbc26f - g_main_context_dispatch
  30:     0x7f3260bbe1b1 - <unknown>
  31:     0x7f3260bbf0c3 - g_main_loop_run
  32:     0x55784c7310c7 - glib::auto::main_loop::MainLoop::run::h59f69fb08fb751ba
                               at /home/jan/.cargo/registry/src/github.com-1ecc6299db9ec823/glib-0.9.1/src/auto/main_loop.rs:46
  33:     0x55784c72ed08 - foo::main::hd596e2be2ba6dd19
                               at src/main.rs:32
  34:     0x55784c72d3f0 - std::rt::lang_start::{{closure}}::h29118bb61f6df9dc
                               at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/rt.rs:61
  35:     0x55784c73a583 - std::rt::lang_start_internal::{{closure}}::h6ea535ec5c50fc3e
                               at src/libstd/rt.rs:48
  36:     0x55784c73a583 - std::panicking::try::do_call::h631c6408dfccc6f5
                               at src/libstd/panicking.rs:287
  37:     0x55784c73bd5a - __rust_maybe_catch_panic
                               at src/libpanic_unwind/lib.rs:78
  38:     0x55784c73afed - std::panicking::try::hab539b2d1255d635
                               at src/libstd/panicking.rs:265
  39:     0x55784c73afed - std::panic::catch_unwind::hd5e0a26424bd7f34
                               at src/libstd/panic.rs:396
  40:     0x55784c73afed - std::rt::lang_start_internal::h3bdc4c7d98181bf9
                               at src/libstd/rt.rs:47
  41:     0x55784c72d3c9 - std::rt::lang_start::ha96fda9eb67ca34b
                               at /rustc/73528e339aae0f17a15ffa49a8ac608f50c6cf14/src/libstd/rt.rs:61
  42:     0x55784c72edaa - main
  43:     0x7f326096f153 - __libc_start_main
  44:     0x55784c72d16e - _start
  45:                0x0 - <unknown>

Time to add more types

A lot of Gio types aren't bound and could certainly be now (either automatically or by hand). I'll take a look.

Simple way of calling `gio::ApplicationExt::run()` with `env::args()`?

I have played around with this for some time, but didn't manage to come up with a nice way of calling fn gio::ApplicationExt::run(&self, argv: &[&str]) -> i32 with std::env::args(). This is what I am doing at the moment, is there a better way?

let args = std::env::args(); // Iterator<Item = String>
let args_vec = args.collect::<Vec<_>>(); // Vec<String>
let args_ref_vec = args_vec.iter().map(|x| &x[..]).collect::<Vec<_>>(); // Vec<&str>

app.run(&args_ref_vec); // auto-deref to &[&str]

Provide a way to use std::io::{Read,Write} and gio::{Input,Output}Stream interchangeably

When you have a std::io::Read, it should be possible to use it with gio-based APIs that require a gio::InputStream. Conversely, when all you have is a gio::InputStream, it should be possible to use it with APIs using std::io::Read. The same goes std::io::Write and gio::OutputStream.

When mixing APIs using the Rust types and the gio types, interaction between streams gets hairy. Writing a wrapper for gio::{Input,Output}Stream that implements Read or Write is straightforward enough, but it's also generally useful so IMO it should be included here. However, if all you have is an std::io::Read, the only way I've found to get that to an API that takes a gio::InputStream is to dump the entire stream into a temporary file and re-open that with gio. I think it should be possible to write a gobject subclass of GInputStream -- either in unsafe Rust or in C -- that simply wraps a std::io::Read. This class would then have to be exposed back to Rust in some form.

So in short, things I'd love to see:

  • a wrapper for gio::InputStream that implements std::io::Read
  • a wrapper for gio::OutputStream that implements std::io::Write
  • a subclass of GInputStream that wraps a std::io::Read and can be passed to wrapped APIs
  • a subclass of GOutputStream that wraps a std::io::Write and can be passed to wrapped APIs

GInputStream / GOutputStream read_all()/write_all() bindings wrong in error case

In case of error, these functions return still how much was actually written as some part of the buffer might've been successfully written (especially in the EWOULDBLOCK case).

See docs

As a special exception to the normal conventions for functions that use GError, if this function returns
FALSE (and sets error ) then bytes_written will be set to the number of bytes that were successfully
written before the error was encountered. This functionality is only available from C. If you need it from
another language then you must write your own loop around g_output_stream_write().

This needs manual bindings for these functions, and does affect the sync and async variants.

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.