r0x0r / pywebview

Build GUI for your Python program with JavaScript, HTML, and CSS
https://pywebview.flowrl.com
BSD 3-Clause "New" or "Revised" License
4.65k stars 540 forks source link

Suggestion: webkit/gtk using ctypes #1466

Open orent opened 1 week ago

orent commented 1 week ago
def load_webkit():
    import os, ctypes
    for line in os.popen('/sbin/ldconfig -p'):
        so = line.split()[-1].strip()
        if 'libwebkit2gtk' in so:
            try: return ctypes.CDLL(so)
            except OSError: pass
    raise RuntimeError('Failed to load webkit library')

def webview(url):
    lib = load_webkit()
    lib.gtk_init(0, 0)
    window = lib.gtk_window_new(0)
    lib.gtk_window_set_default_size(window, 800, 600)
    lib.g_signal_connect_data(window, b'destroy', lib.gtk_main_quit, 0, 0, 0)
    wv = lib.webkit_web_view_new()
    lib.gtk_container_add(window, wv)
    lib.webkit_web_view_load_uri(wv, url)
    lib.gtk_widget_show_all(window)
    lib.gtk_main()

if __name__ == '__main__':
    webview(b'https://www.google.com')

This code should work on virtually any system where some version of webkit2gtk is installed, without requiring python gtk or gobject support. It can run from a standalone python interpreter inside a bundled application. It even happens to run unmodified on an old RHEL7 system with python2.

Would it be a good idea to make a backend based on this? I couldn't get pywebview to work on some systems because of python and gtk issues and I think this could make it much more likely to work out-of-the-box in more situations.

r0x0r commented 1 week ago

Sounds like a good idea to me. When loaded this way what does API look like? And what it would involve converting current code into the ctypes format?

orent commented 1 week ago

The api is exactly the C api. This means, for example, that there is no automatic destruction of gobjects by Python refcnt going to 0.

This example uses only ints, null terminated strings and opaque object pointers. Some APIs also need structs that would need to be translated to ctypes Struct and values of defines/enums.

r0x0r commented 5 days ago

My main concern about this is that the implementation will become unruly. My C skills are rusty and chasing memory leaks is not something I am prepared to spend time on. Having said that, I don't know how much of the implementation can be kept in Python and what needs to be converted to C. It might be worth pursuing if the complexity of the end result is not too far off from the current one.

orent commented 5 days ago

Wrapping the objects in ctypes Structs with a destructor should not be too hard. The result can be virtually identical to existing interface.

Are there any cases with tricky object ownership semantics where e.g. the Python destructor may prematurely destroy an object that a C object needs to retain? I think I can let Claude read the gobject docs and APIs for the functions used and point them out. It would be a nice exercise in AI use.

r0x0r commented 2 days ago

Are there any cases with tricky object ownership semantics where e.g. the Python destructor may prematurely destroy an object that a C object needs to retain?

I don't know to be honest.

Anyway, if you feel like doing this, feel free to go ahead. Two GTK implementations can co-exist at the same time, so there is no pressure to replace the existing one just yet.

orent commented 2 days ago

My tiny example is actually good enough to be useful as a quick’n’dirty UI component for a python script with an http server on localhost. But pywebview uses a much larger subset of the api so it would probably mean implementing a fair bit of gi with ctypes.