-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Python Bindings under Emscripten? #21
Comments
@gabriel-v would you mind give try with https://github.com/pygame-web/python-wasm-sdk ? use |
Hi, wow, you're adventurous :) I never even thought the python bindings would be useful under Emscripten, so the code doesn't contain any Emscripten-/WebGL-specific handling at the moment. For the
For the build errors, the bindings codebase doesn't handle a case of plugin managers without dynamic library support (i.e., diff --git a/src/python/corrade/pluginmanager.cpp b/src/python/corrade/pluginmanager.cpp
index 487bf06..1d5c436 100644
--- a/src/python/corrade/pluginmanager.cpp
+++ b/src/python/corrade/pluginmanager.cpp
@@ -42,16 +42,21 @@ void pluginmanager(py::module_& m) {
py::enum_<PluginManager::LoadState> loadState{m, "LoadState", "Plugin load state"};
loadState
.value("NOT_FOUND", PluginManager::LoadState::NotFound)
+ #ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT
.value("WRONG_PLUGIN_VERSION", PluginManager::LoadState::WrongPluginVersion)
.value("WRONG_INTERFACE_VERSION", PluginManager::LoadState::WrongInterfaceVersion)
.value("WRONG_METADATA_FILE", PluginManager::LoadState::WrongMetadataFile)
.value("UNRESOLVED_DEPENDENCY", PluginManager::LoadState::UnresolvedDependency)
+ #endif
.value("STATIC", PluginManager::LoadState::Static)
.value("LOADED", PluginManager::LoadState::Loaded)
+ #ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT
.value("NOT_LOADED", PluginManager::LoadState::NotLoaded)
.value("UNLOAD_FAILED", PluginManager::LoadState::UnloadFailed)
.value("REQUIRED", PluginManager::LoadState::Required)
- .value("USED", PluginManager::LoadState::Used);
+ .value("USED", PluginManager::LoadState::Used)
+ #endif
+ ;
corrade::enumOperators(loadState);
PyNonDestructibleClass<PluginManager::AbstractManager> manager{m, "AbstractManager", "Base for plugin managers"};
@@ -61,6 +66,7 @@ void pluginmanager(py::module_& m) {
/** @todo drop std::string in favor of our own string caster */
return std::string{self.pluginInterface()};
}, "Plugin interface")
+ #ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT
.def_property("plugin_directory",
/** @todo drop std::string in favor of our own string caster */
[](PluginManager::AbstractManager& self) {
@@ -69,6 +75,7 @@ void pluginmanager(py::module_& m) {
self.setPluginDirectory(directory);
}, "Plugin directory")
.def("reload_plugin_directory", &PluginManager::AbstractManager::reloadPluginDirectory, "Reload plugin directory")
+ #endif
/** @todo setPreferredPlugins (takes an init list) */
.def_property_readonly("plugin_list", [](PluginManager::AbstractManager& self) {
/** @todo make a generic caster for arbitrary arrays and strings */ For the GL errors it's similar, the codebase is currently handling differences between GL and GLES (which is a subset of GL), but it doesn't handle WebGL differences (which itself is an even more restricted subset of GLES). A patch that attempts to fix at least some of these is below: diff --git a/src/python/magnum/gl.cpp b/src/python/magnum/gl.cpp
index 533f481..4498492 100644
--- a/src/python/magnum/gl.cpp
+++ b/src/python/magnum/gl.cpp
@@ -307,6 +307,7 @@ void gl(py::module_& m) {
{
py::class_<GL::Context, ContextHolder<GL::Context>> context{m, "Context", "Magnum OpenGL context"};
+ #ifndef MAGNUM_TARGET_WEBGL
py::enum_<GL::Context::Flag> contextFlag{context, "Flag", "Context flag"};
contextFlag
.value("DEBUG", GL::Context::Flag::Debug)
@@ -319,6 +320,7 @@ void gl(py::module_& m) {
#endif
.value("NONE", GL::Context::Flag{});
corrade::enumOperators(contextFlag);
+ #endif
py::enum_<GL::Context::State> contextState{context, "State", "State to reset"};
contextState
@@ -844,6 +846,7 @@ void gl(py::module_& m) {
.value("STENCIL", GL::FramebufferClear::Stencil);
corrade::enumOperators(framebufferClear);
+ #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
py::enum_<GL::FramebufferBlit> framebufferBlit{m, "FramebufferBlit", "Mask for framebuffer blitting"};
framebufferBlit
.value("COLOR", GL::FramebufferBlit::Color)
@@ -854,6 +857,7 @@ void gl(py::module_& m) {
py::enum_<GL::FramebufferBlitFilter>{m, "FramebufferBlitFilter", "Framebuffer blit filtering"}
.value("NEAREST", GL::FramebufferBlitFilter::Nearest)
.value("LINEAR", GL::FramebufferBlitFilter::Linear);
+ #endif
py::class_<GL::AbstractFramebuffer, NonDefaultFramebufferHolder<GL::AbstractFramebuffer>> abstractFramebuffer{m,
"AbstractFramebuffer", "Base for default and named framebuffers"};
@@ -862,12 +866,14 @@ void gl(py::module_& m) {
/** @todo limit queries */
/* Using lambdas to supply an enum and not enum set */
+ #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
.def_static("blit", [](GL::AbstractFramebuffer& source, GL::AbstractFramebuffer& destination, const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, GL::FramebufferBlit mask, GL::FramebufferBlitFilter filter) {
GL::AbstractFramebuffer::blit(source, destination, sourceRectangle, destinationRectangle, mask, filter);
}, "Copy a block of pixels", py::arg("source"), py::arg("destination"), py::arg("source_rectangle"), py::arg("destination_rectangle"), py::arg("mask"), py::arg("filter"))
.def_static("blit", [](GL::AbstractFramebuffer& source, GL::AbstractFramebuffer& destination, const Range2Di& rectangle, GL::FramebufferBlit mask) {
GL::AbstractFramebuffer::blit(source, destination, rectangle, mask);
}, "Copy a block of pixels", py::arg("source"), py::arg("destination"), py::arg("rectangle"), py::arg("mask"))
+ #endif
.def("bind", &GL::AbstractFramebuffer::bind, "Bind framebuffer for drawing")
.def_property("viewport", &GL::AbstractFramebuffer::viewport, &GL::AbstractFramebuffer::setViewport, "Viewport")
/* Using lambdas to avoid method chaining getting into signatures */ I don't have an easy way to verify that the patches are complete, so it will likely need more Hope this helps -- and of course I'll be very happy to integrate your patches once you get this to build :) |
Oh, and one other thing that might be a source of pain is the Sdl2Application library that the current Python examples rely on -- hopefully it will work as-is (enable it with The go-to application to use on the web would be The windowless / EGL applications could also work there, but are not essential for anything -- they're used just by unit tests. |
I tried to build the python bindings under emscripten.
Here's how it went:
1. LONG_BIT definition appears wrong
First, a CPython-related compilation error in Python about
LONG_BIT
mismatchThis is similar to what other people have been asking in pyodide and in pybind11. The pyodide issue seems to have been fixed in 0.22 but I can't figure out what they did.
I also looked into cross compiling python with wasm/wasi using upstream CPython3.11 - it doesn't raise the
LONG_BIT
error there.I guess we are either missing some emscripten compiler configs in the toolchain, or some python build configurations - the system target arch there are called
wasm32-unknown-emscripten
instead of justemscripten
.Here is the emconfigure command for compiling python with emscripten vs. magnum emscripten toolchain, we probably have to reproduce the effects of these arguments:
So I ignored it and patched it out to see what's next.
2. Missing Symbols: corrade plugin manager; magnum GL bindings
I suppose the corrade plugins manager doesn't compile because of missing functionality in emscripten, and the
gl.cpp
binding fails because we only have EGL not GL.I'm willing to work on adding python support to your bindings as a hobby project of mine - do let me know if you have any tips!
Would it be possible to write bindings to have Python bindings code in the browser?
The text was updated successfully, but these errors were encountered: