Coder Social home page Coder Social logo

grust's People

Contributors

matze avatar mzabaluev 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

grust's Issues

Figure out callbacks

We need to figure out the semantics of passing safe callbacks from Rust to GObject:

  • What type and sigil should the callback closure have.
  • Which task it is to be called in.

Reconsider the ownership/concurrency model

The cross-thread call paths are an albatross for code size, performance, and they use a sentinel thread with a statically unpredictable failure mode in case of a deadlock. Reducing to on-stack FFI calls with single-task ownership for all Rust boxes of a GObject seems like a more practical approach.

The battle plan after an IRC discussion with @strcat:

  • Make the cloneable, refcounting Reference wrappers non-sendable.
  • The non-cloneable, sendable wrappers (Object?) ref the object on construction and unref it in the Drop implementation.
  • Add an Object method to move self into a Reference;
  • maybe add a Reference method to move self into an Option<Object<T>>,
    with None returned when the reference count is more than one.
    It's not clear how to do this without parallel refcounting or GObject toggle references
    and additional state in each Reference.

Use macros to reduce repetition

Rust's powerful macro system can greatly improve readability for the generated code and facilitate creation of bindings by hand, should such a need arise.
Ideally, declarations of binding types for GObject could look like this:

gobject_decl! {
    class FileInputStream : InputStream {
        type_fn g_file_input_stream_get_type();
    }

    sync class Cancellable {
        type_fn g_cancellable_get_type();
    }

    interface AsyncResult {
        type_fn g_async_result_get_type();
    }
}

The type structs and much of the boilerplate traits for type ID, casting and wrapping can be generated from such compact descriptions.

Another area to benefit from macroization is transformation of parameters and output values between Rust and C.

Ensure thread safety for calls

GObject-based objects are not generally thread-safe, so it may not be safe to call GObject methods directly from different concurrent tasks. If we freely allow cloning and sending wrapped GObject references in safe Rust code, we should forward all GObject calls through a dedicated long-running task. grust::init could be the place where this task is started.

Ensure the event loop model is sound

We have the GMainLoop event loop(s) which many GLib based libraries rely on for running. We also have Rust task event loops that are based on libuv. Interaction between the two is bound to be interesting. This is another part of the puzzle together with #2 and #3.

Look into a generation mode for single-threaded libraries

There are libraries, most notably Gtk+ and GDK,that expect all their usage to occur within a single thread, except for some thread-safe functions and objects. To bind these libraries safely, it seems necessary to generate code differently, passing a reference to a non-sendable global context object to every function that is not designated thread-safe or does not use some non-sendable objects from the same library.

Typically, such libraries have one or more initialization functions of which one must be called before any other use of the library can occur. These can be represented in Rust by functions returning the library context value.

Does not support out of tree builds

Hi! First I'd like to say I'm really happy that this project is in progress. I think it's going to be really cool when bindings to cool libraries like gtk, and libpeas can be automatically generated. Second, I'd like to report an issue. This project does not work with out of tree builds. For example, I moved to a different directory builds/grust from the directory projects/grust, and ran the command ../../projects/grust/configure, and though the project was succesfully configured the Makefile failed to build the project properly. I'd be wiling to help out on solving this issue as I have experience working with autotools but I am unfamiliar with the source of this project.

Figure out type casting

A solution is needed for dynamic down- and side-casting between traits representing GObject interfaces.
It should be as idiomatic Rust as possible, and invoke GObject dynamic cast checks.

A sendable reference type for objects not parked in a thread

There are cases when an object can be sent to another thread as long as no other references to it exist in safe code.
Add a sendable reference type NewRef with the following features:

  • Derefs to the object
  • Implements Send
  • Does not implement Clone
  • A method or function, tentatively named park(), promotes a NewRef into Ref, effectively parking the object in the calling thread.

See some rationale in a comment on the GObject-introspection bug regarding thread-safety annotations.

Figure out error handling

We need to find a way to represent GLib errors in Rust that is: 1) as idiomatic Rust as possible; 2) able to provide all information of a GError value.

The current prototype code in fauxgen simply takes the message out of a GError to pass to fail!(), which is lossy and provides no way to match and handle recoverable errors.
There is talk on the mailing list about "conditions" as a more versatile mechanism of handling errors, but none of that can be found in the documentation yet.

If conditions do not become available, my reserve idea is to have an ErrorContext trait which can be used to create a temporary object encapsulating a mutable GError pointer for each call site, pass a pointer to the pointer to the C function and call the desired error handling behavior from the temporary's destructor. Different implementations of ErrorContext can ignore errors, fail on them, or do something more sensible depending on the error data. Usage of built-in error handling contexts can be facilitated by helper functions:

grust::fail_on_errors(|err_ctx|, {
    obj1.throwing_method1(err_ctx.get());
    obj2.throwing_method2(err_ctx.get());
});

Reboxification of async callbacks

Consider passing the async callback closures (FnOnce) in boxes.
For performance it's likely better if the closure is constructed boxed at the call site.

My attempt to implement this has run into an ICE which looks to be rust-lang/rust#20676.

Bindings for values that can be on-stack or refcounted

There are GLib types: GVariantBuilder, GVariantDict, and GVariantIter, that can be heap-allocated and then refcounted, or be created on stack which naturally does not allow refcounting.
Bindings for each of these would likely require three different types:

  • an on-stack type, calling on-stack cleanup in Drop;
  • a type implementing Refcount to represent heap-allocated structures;
  • a type that implements most of the bound methods, with an AsRef-style conversion from the two types described above.

Cargoize

Should package for, and build with Cargo.
Also verify what is needed to provide Cargo infrastructure for generated crates.

What happened to the project?

I like the idea of explicit Ref smart pointer more than gtk-rs approach. I think it is better because:

  1. When reading the code, you immediately see that it is just a reference, and it's obvious that .clone() will only create a new reference

  2. It seems that GObject subclassing would be easier this way (compared to current gtk-rs)

However, I see that there has been no commits since 2018. Why? Are there any fundamental issues in this project that can't be resolved?

Address the case of g_variant_builder_end()

The documentation says:

It is not permissible to use [the GVariantBuilder instance] in any way after this call
except for reference counting operations (in the case of a
heap-allocated GVariantBuilder or by reinitialising it with
g_variant_builder_init() (in the case of stack-allocated).

In the bindings, this may mean:

  • The binding method or function for this operation would consume some value owning a GVariantBuilder as a by-value parameter (likely self). It's interesting to support the stack-allocated case as well, so the method may need to be generic over some trait covering both cases.
  • Normal semantics of grust::refcount::Ref would not work safely, as we need the reference to be unique by the time this call is made, or somehow drop all references immediately afterwards.

Same applies to g_variant_dict_end().

An augmentation system for metadata missing in GObject-introspection

We are likely to need more metadata on the types and functions than what GObject-introspection currently provides.

For #13 and other similar cases, we need a thread safety annotation. I have filed a bug on GObject-introspection, but pending any action on that (and I'm not holding my breath), an in-project solution is needed to augment the GIR data with thread-safety attributes.

Some types and methods need to be blacklisted. In Glib and GObject, we don't want bindings for types that will be supported intrinsically by Grust.

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.