electronstudio / raylib-python-cffi

Python CFFI bindings for Raylib
http://electronstudio.github.io/raylib-python-cffi
Eclipse Public License 2.0
159 stars 31 forks source link

Raylib-Python-CFFI on the web #58

Open Yu-Vitaqua-fer-Chronos opened 2 years ago

Yu-Vitaqua-fer-Chronos commented 2 years ago

Heya, I looked though all of the issues and found #45 stating that it wasn't supported but projects like Pyodide exist now and allow you to run your Python code in the web via WebAssembly, and it's also possible to use C modules on the web as long as it's compiled for use with Pyodide. I think it'd be a neat addition and worthwhile to look into, thanks for your time!

electronstudio commented 2 years ago

There was a lot of discussion of this on the Raylib Discord group, but I haven't had time to check that for a while.

Pyodide for a long time had a blocker with.... i think cffi not working(?). When that was fixed I did make an attempt because it sounds like it should be possible, but just getting Pyodide to compile was a ridiculous process - even their own docker image created for that purpose didn't work.

There's also https://github.com/plasticityai/coldbrew that might be worth trying.

It would be cool if it 'just worked' but it's not something I have a real use for at the moment so I doubt I will have time - someone else would have to do it.

Yu-Vitaqua-fer-Chronos commented 2 years ago

Fair enough haha

captain0xff commented 2 years ago

There's another project that can be used https://github.com/ethanhs/python-wasm instead of pyodide

electronstudio commented 2 years ago

I tried again with latest Pyodide docker image.

It is necessary to delete any EM_ASM and EM_JS macros from Raylib, because these can only be used in a 'main' WASM module, i.e. Pyodide itself, and not in any 'side' modules that it loads. Command to compile Raylib is /src/emsdk/emsdk/upstream/emscripten/emcmake cmake -DPLATFORM="Web" -DCUSTOMIZE_BUILD=ON -DWITH_PIC=on -DBUILD_EXAMPLES="OFF" -DSUPPORT_MODULE_RAUDIO=OFF -DUSE_AUDIO=OFF ..

However, the resultant wheel still will not load. It's not the only wheel that won't load, other wheels that are shipped with Pyoxide such as CFFI also fail to load, so it may not be anything Raylib specific. There's no error given so next steps would be:

  1. Figure out how to make Pyodide print actual errors.
  2. Find example of Pyodide loading modules like CFFI that works.
  3. Try the dynamic loading .so version of Raylib Python CFFI
sDos280 commented 2 years ago

@electronstudio in the last past few days I have been trying to compile python with Nuitka and an idea just came to my mind. what if it is possible to compile python to CPP using Nuitka and then compile the CPP code to webassembly...

please let me know if you think this may work

also, let's try to build the dynamic library first because as I can see it, it is much easier to use this dynamic loading with cffi than generate a lib file using cffi, but I may be wrong on that...

sDos280 commented 2 years ago

Or even using cython compiler to generate the C code and then compile it to the web

https://stackoverflow.com/questions/6985109/how-to-compile-c-code-from-cython-with-gcc

https://stackoverflow.com/questions/32354762/unable-to-compile-cython-generated-c-file

I didn't try those yet, but I will try

sDos280 commented 1 year ago

@electronstudio great news, while working on my binding it seems that someone was able to port it to webassembly
take a look: https://github.com/sDos280/raylib-python-ctypes/pull/9 , https://pygame-web.github.io/showroom/raylib/

Started to work on some documentation. https://github.com/sDos280/raylib-python-ctypes/issues/10

pmp-p commented 1 year ago

Hi, here's the someone from previous post :) 1) pyodide cannot load SDL2 or GLFW or GLES/GL bridge because it is not compiled in the main module, critical javascript "os" glue is missing 2) there's a bug in emscripten that will prevent loading shared libraries

pygbag offers a runtime that fixes all that, https://pypi.org/project/pygbag we host files at pygame-web github pages and we now have a wheel for @sDos280's work

you can even run gist snippets eg https://pygame-web.github.io/showroom/pypad.html#https://gist.githubusercontent.com/pmp-p/1c41aeedb6a165c6a5cd994c530b233d/raw/91dbfedbd901c9c23ead4195471c45f4ed330664/test_rl_julia.py

pmp-p commented 8 months ago

pygame-web now provides a raylib-5.0.0.1-cp310-abi3-wasm32_bi_emscripten.whl wheel eg https://pygame-web.github.io/showroom/pythongit.html?cpython3.13#src/test_raylib.py

source https://github.com/pygame-web/showroom/blob/main/src/test_raylib.py

nb: InitWindow() could need a fix for forcing canvas so hardware scaler (css) sync to new size after init that's why there is a pygbag specific call in the sample

    import platform
    platform.window.window_resize()
electronstudio commented 8 months ago

Looks cool.

The raylib package has a dependency on the inflection package, so when I try to use any of the pyray functions I get

ModuleNotFoundError: No module named 'inflection'

How can I add inflection?

pmp-p commented 8 months ago

for scripts adding "inflection" to the PEP 723 block should allow integrated pypa/installer to get the pypi wheel at runtime.

Another way is to unzip the wheel/source folder of desired version next to main.py when using pygbag packager ( pygame-scripts harder to use when dealing with lot of assets )

electronstudio commented 8 months ago

I added inflection to the PEP 723 block but it does not seem to make any difference. Here is the whole project so you can see what I'm doing wrong:

https://github.com/electronstudio/raylib-python-cffi-pygbag-examples

pmp-p commented 8 months ago

it seems automatic install from pypi is failing for "inflection" i'll look into making a wheel right now

btw if you are interested in no hassle automatic wheel build you could vendor pygbag into building raylib-python-cffi, i already have the necessary pipeline that build raylib+python with python-wasm-sdk available ( and as i maintain it you don't have to fight with raylib/python/emsdk changes ) .

exemple of pygbag vendoring https://github.com/harfang3d/harfang-wasm or https://github.com/pmp-p/panda3d-wasm ( vendor + packages.d folders )

pmp-p commented 8 months ago

ho i found why, inflection is a py2/py3 module and parser does not account yet for those wheels, i'll fix that asap shot-2024-02-21_1708491257

yep got it with py -m pygbag --PYBUILD 3.12 --git --ume_block 0 --template noctx.tmpl main.py locally, cdn should update in about half an hour

pmp-p commented 8 months ago

cdn is updated ! it should work locally and in CI https://pmp-p.github.io/raylib-python-cffi-pygbag-examples/

yml typical for raylib is a bit different from pygame because of 2D/3D context switch so here it is https://github.com/pmp-p/raylib-python-cffi-pygbag-examples/tree/master/.github/workflows

electronstudio commented 8 months ago

Thanks, that is great. I put up some examples here: https://electronstudio.github.io/raylib-python-cffi-pygbag-examples

I'm not sure the platform.window.window_resize() fix is working, some of them seem to have wrong size

pmp-p commented 8 months ago

I'm not sure the platform.window.window_resize() fix is working, some of them seem to have wrong size

Seems that pyray.init_window() is not setting canvas render buffer size correctly, i'll have a look to raylib internals. Normally canvas.width and height should match init_window() called values, while canvas.style.width and height handle hardware scaler (screen pixel values ) it is important to fix that to avoid huge drop of perf on mobile.

electronstudio commented 8 months ago

@pmp-p I'm not sure what you mean by vendoring. Currently all the binary wheels are built on github actions https://github.com/electronstudio/raylib-python-cffi/blob/master/.github/workflows/build.yml and cirrus CI https://github.com/electronstudio/raylib-python-cffi/blob/master/.cirrus.yml . Is there an easy way to add the wasm binary wheels to one of these?

sDos280 commented 8 months ago

Looks cool.

The raylib package has a dependency on the inflection package, so when I try to use any of the pyray functions I get

ModuleNotFoundError: No module named 'inflection'

How can I add inflection?

Hi, electron-studio and pmp. it has been a long time. I saw that you had the same problem as I had the first time I tried to use python on the web (with raypyc).

the same as you I used inflection for the underscore function. back then I didn't know how to fix it so I just settled by copying inflection underscore code to my project (with the reference to the inflection library):

def underscore(word: str) -> str:
    """
    Make an underscored, lowercase form from the expression in the string.

    Example::

        >>> underscore("DeviceType")
        'device_type'

    As a rule of thumb you can think of :func:`underscore` as the inverse of
    :func:`camelize`, though there are cases where that does not hold::

        >>> camelize(underscore("IOError"))
        'IoError'

    """
    word = re.sub(r"([A-Z]+)([A-Z][a-z])", r'\1_\2', word)
    word = re.sub(r"([a-z\d])([A-Z])", r'\1_\2', word)
    word = word.replace("-", "_")
    return word.lower()

hope that would help.

pmp-p commented 8 months ago

the idea of vendoring is to inherit current pygbag build, so the ABI matches when building the wheels ( eg in case of emscripten changes or new python version). For pygbag 0.9+ i will start to add a WASI testsuite for CI, the wheels will benefit of that too.

And then later i can setup a script that will grab the released wheels and merge them in the main "pypi" repo

I find that way lib dev would be more in control of their wasm packages.

Pyodide (which anyway is not made for games loops) and others are more difficult to publish since you have to put a recipe in their repo + patches and have no control over main flags.

if you fork pygbag renamed to "pygbag-raylib" or "raylib-wasm" i can PR the build scripts so you can get an idea of the WIP. Also it is good for handling specific raylib issues by activating them on the fork. I already found some with shaders.

@sDos280's idea for inflection seems to load way faster than grabbing the pypi wheel and it is not much code to maintain

pmp-p commented 8 months ago

ho i also forgot the main argument for using pygbag as wheel builder, it is FAST ( less than 5 minutes ) while a full CI for wasm would take more than 30 minutes ( get emsdk, build thirdparties ( emsdk ports + python + raylib ) , build the wheel )

electronstudio commented 8 months ago

ok forked https://github.com/electronstudio/pygbag-raylib