Hacking Swift runtime

Greetings.

I would like to improve a Swift GTK wrapper. There is an issue that has been bothering me for a while.

GTK is a C library which is based on GObject object system. The Swift wrapper already creates a Swift class definition for GObject base class and each of it's children.

My objective is to synchronize the lifecycle of GObject instance and it's Swift wrapper.

I am able to pass an opaque pointer of a Swift wrapper instance to the GObject and release it upon the GObject instance destruction. Therefore I am able to ensure, that at most 1 Swift wrapper instance is living at any time.

My problem is, that I need to release the Swift instance and the GObject instance only when there is no strong reference in either ARC (or a floating one in GObject).

Since hacking the GObject ref (retain) and unref (release) functions is not an option, I've focused on the Swift runtime. By reading https://belkadan.com/blog/2020/08/Swift-Runtime-Heap-Objects/ and https://github.com/wickwirew/Runtime I think I have all I need to achieve my objective already.

My question is, whether I can "swizzle" a runtime method in the same manner as in Objective-C. I would like to perform some additional operations for instances of Swift wrappers and then call the original swift_retain.

Hi @stuchlej

Can you take a look at https://github.com/svanimpe/gtk-swift/tree/master/Sources/GTK?
I did some experimenting with creating a Swift wrapper around GTK earlier this year, and that's how far I got before I had to move my attention elsewhere.

My approach was to store a pointer to the GObject in the Swift wrapper and call g_object_unref in the deinitializer. That deallocated both the Swift object and the GObject.

It sounds like you're going much deeper than I did, but I'd love to hear your thoughts on what I did, as it's a project I'd love to finish sometime next year.

Hi!

I have forked Rene Hexel's wrappers (https://github.com/rhx/SwiftGtk) I intend to explore possibilities for improvements (like this) and merge whatever ends up useful. The rhx's implementation shares the same approach as you. I will take a look.

Meanwhile for the context :) : I've already done some work on signals (passing Swift closures to GObject signals). This is the reason why I explore this particular problem. Consider following example:

let button = Button(label: "a button")
let label = Label(text: "a text")
button.onClicked { _ /*a ButtonRef instance - struct with unowned reference to the caller*/ in 
    label.text = "button event"
}

The onClicked closure has taken a strong reference to the label instace. However if I captured a weak reference instead (as I would like to do), the label would deallocate and I would end up with nil value during the call of the signal.

I've looked at your project.

While there is nothing wrong with it, I would like to warn you in advance. I've already seen some hand-written wrappes (on github, by TomasLinhart and fork by the GothStar (btw what a nickname :D )). There are two main issues with hand written wrappers when it comes to GTK. The first issue is the size of the codebase. GTK with all of it's dependencies has hundrets of types and untold number of functions. The second issue is, that there is a lot of versions of Gtk+ available and you might end up with compatibility issues if you "ship" wrapper code directly. There is a solution to this problem, called GObjectIntrospection. Tho GI is not only able to procude xml files describing the C API but it can serve as a middleware too ( I have never tried it tho).

Thinking about it, maybe we can create some Discord (or Slack) channel for Swift GTK (like Swift ARM) :)

2 Likes

In the thread "Object was retained too many times",
A Foundation retain-release leak was debugged by modifying the Swift Runtime, IIRC.
It might be useful.

Thank you!
I've seen this thread in the past but I was unable to find it.

I think this reply "Object was retained too many times" might be the solution :)

Edit: I can confirm this is exactly what I was searching for. Thank you again :) If anyone had anything to say about the topic (main why I should never try to do something like this :)) please let me know. From my perspective this seems as a reasonable thing to try. Slowing the Swift a bit is not a dealbreaker for me.

I don’t mean to hijack this topic, but I recently did a small experiment wrapping GTK in a SwiftUI-like api (using the excellent Tokamak library).

I based my experiment on Rene Hexel’s wrappers too:

I have implemented Text, HStack, VStack and Button - and I have gotten the update loop to work, so that the UI can change dynamically.

Finally I have hacked together support for a single modifier.

It’s all just a proof-of-concept, and I don’t have any plans to build it out much further, but I would like to clean it up for sharing if anyone is interested.

I am on a macOS machine, so I use Dispatch for a simple scheduler, but I assume that this can quite easily be replaced by something else on Linux - it’s only used in a couple of lines of code.

2 Likes

I pushed my code to github. Tokamak is currently added manually since the TokamakCore target cannot currently be referenced directly.

The whole thing is not yet wrapped up in a library, but I hope that it can still be of inspiration.

Here's a screenshot of a sample view:

5 Likes

I welcome all people working on Gtk+, don't mind the topic. As I mentioned above, maybe it would be worth to organize a little bit better.

As for people using Rhx's codebase, I think he has done a great deal of work and we need to resolve some issues which makes it harder for Swift devs to participate and/or use Gtk.

Maybe starting some wiki about the project and share our experiences better. I think the biggest weakness of Rhx's work is, that the project is a little bit confusing when it comes to inner workings of gir2swift and the post processing phase with xed and sed.

I think there is clearly a demand for Swift wrapper and a good will to do some work. We just need to make it far mor easier for people to participate.

Edit: I have also started using gtk, I'll be using it in the future for any Gtk related threads. (Tags can be subscribed to.)@Morten_Bek_Ditlevsen @svanimpe

3 Likes

@stuchlej The main reason I didn't use the rhx bindings, is that they surface too much of GTK's internals for me.

My goal was to have a UI framework on Linux that is good enough for me to teach the fundamentals of event-driven UI. I wanted a framework that looks like a Swift framework and that students can learn/use without having to know anything about GTK or GObject. The less API I have to expose, the better!

I'm not sure how far my approach will get me, but so far, it seems like it will at least make a useful teaching tool :slight_smile:

3 Likes

Hi everyone,

I’m a little late responding to this after 6 months, please forgive me that - I think it’s more important than it seems. Swift can become the default language for writing gtk and Gnome apps. I think this would be huge and would bring new developers and ideas to the ecosystem and boost Gnome development. Or is it already happening with some other language or something? Maybe I’m late not only in this this topic.

I was wondering if adding a new attribute like @gobject to LLVM and create the required wrappers and other scaffolding code there, at the compiler level would be something that people would look forward to. Is the current solution easy and complete enough?

Hello.

There are a lot of things worth addressing.

Gnome project
Gnome project (especially libraries like GLib/GObject, GTK) is a mature project with a lengthy history. One of the aims of GLib/GObject libraries is to provide C API that is bindable by other languages. Therefore the GTK library is already accessible from almost all most common languages. I am not that knowledgable about various GNOME projects, but I saw most GTK apps written in C, Vala, Python or JS.
Therefore I would say, that "Swift needs GTK more then GTK need Swift". I would also say, that Swift won't became mainstream amongst GTK developers since Swift is Apple owned and controlled language which would contrast with the philosophy of the GNOME project originating in GNU.

The Swift bindings for GLib/GObject, GTK
The GTK (and it's dependencies) is a huge codebase. The public API and documentation itself is hundreds of thousands of lines. Since all of the APIs are in C, you are free to use the GTK from Swift already.
The quest for more idiomatic Swift interface for GLib/GObject or GTK is a tough one. The most viable approach is to generate Swift wrapper for C APIs. This can be done already, since GLib/GObject libraries can take advantage of project called gobject-introspection which (amongst many things) produces XML metadata files with extension .gir. Those .gir files are distributed alongside with developer versions of GLib/GObject and GTK libraries.
There is already a project which generates .swift interfaces based on metadata in .gir files called gir2swift.

The gir2swift project
The gir2swift project GitHub - rhx/gir2swift: A simple GIR parser in Swift for creating Swift types for a .gir file is a part of wider initiative to provide GTK bindings to Swift developers know as SwiftGtk GitHub - rhx/SwiftGtk: A Swift wrapper around gtk-3.x and gtk-4.x that is largely auto-generated from gobject-introspection.
I am a contributor to both projects. The gir2swift already implements a lot of features but the project is (in my opinion) in dire need of refactoring to make it more Swift-idiomatic and understandable for wider audience of open source developers willing to contribute. If you consider contributing, feel free to contact me with any issue and I will try to help as much as I would be able to.

Better Swift support
I would say, that we won't ever be able to achieve as seamless integration of GLib/GObject into Swift as we are used to from CF/ObjC. The Swift language, being the property of Apple, was designed to be compatible with ObjC.
Even as "simple" task as bridging GType fundamentals and collections would be a major undertaking, not even talking about subclassing GObject class in Swift.
It is my opinion, that the first step towards that future is building a community around the SwiftGtk and gir2swift project. I don't think Apple is "going to give us GTK wrapper for free".

1 Like
Terms of Service

Privacy Policy

Cookie Policy