pywebview icon indicating copy to clipboard operation
pywebview copied to clipboard

Suggestion: webkit/gtk using ctypes

Open orent opened this issue 1 year ago • 7 comments

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.

orent avatar Sep 09 '24 15:09 orent

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?

r0x0r avatar Sep 09 '24 20:09 r0x0r

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.

orent avatar Sep 10 '24 08:09 orent

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.

r0x0r avatar Sep 13 '24 12:09 r0x0r

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.

orent avatar Sep 13 '24 16:09 orent

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.

r0x0r avatar Sep 15 '24 20:09 r0x0r

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.

orent avatar Sep 16 '24 05:09 orent

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

github-actions[bot] avatar Oct 17 '24 02:10 github-actions[bot]

The message to post on the issue when closing it. If none provided, will not comment when closing an issue.

github-actions[bot] avatar Oct 22 '24 02:10 github-actions[bot]