Skip to content

Making dynamic libraries work for Python #5276

@adewes

Description

@adewes

First of all: Thanks for building this, it's an amazing project!

I'm trying to use the dynamic linking capabilities of emscripten to compile the Python interpreter as a shared library and import it at runtime. My motivation for this is that I would like to be able to compile Python modules that rely on C extensions (e.g. numpy) and then import these modules dynamically at runtime (which should be possible via dlopen in my understanding).

I started off from from https://github.com/dgym/cpython-emscripten (which works fine when compiling Python statically) and modified the Makefile to build a shared library in addition to the static Python library. This works fine but I run into a problem when importing the library at runtime, as described here:

dgym/cpython-emscripten#1

Before starting to debug this in depth I first wanted to make sure that I correctly set up the build process, hence my question. What I did to generate the dynamic library is the following:

  • Compile the Python interpreter into a shared library using emcc (I did not use SIDE_MODULE=1 in the build step for this). This gives me a libpython3.5.so file (which contains LLVM bitcode).
  • Converting the shared library into a Javascript library by running emcc -s SIDE_MODULE=1 libpython3.5.so -o libpython3.5.js. This works fine.
  • Compiling my example program with MAIN_MODULE=1 without explicitly linking in the static Python library.
  • Inserting the following code to import the dynamic library:
EM_ASM({
  Runtime.loadDynamicLibrary('/libpython3.5.js');
}); 
  • Initializing the Python interpreter using Py_InitializeEx(0).

Is this the correct way to build and use a dynamic library in this case?

The last step produces an error Python error: Py_Initialize: can't import _frozen_importlib which breaks many things and keeps the interpreter from initializing properly. The core of the interpreter seems to work though (as I can run simple code like 1+1 but not import anything or even print the results).

I created a Gtihub-hosted version with the failing example for easier debugging (it takes a while to load):

http://www.andreas-dewes.de/cpython-emscripten/dll/

The build config for the Python interpreter can be found here:

https://github.com/adewes/cpython-emscripten/tree/master/3.5.2

The build config for the example script is here:

https://github.com/adewes/cpython-emscripten/tree/master/examples/07-dll-loading

Any idea where the problem could be or how I could better debug this? Please let me know if you need any more information, it would really be great to get this working!

In general, is my understanding correct that it should be possible to dynamically load Python libraries through dlopen?

Emscripten version information:

clang version 4.0.0  (emscripten 1.37.13 : 1.37.13)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /home/[....]/emsdk-portable/clang/e1.37.13_64bit
Found candidate GCC installation: /usr/lib/gcc/i686-linux-gnu/6
Found candidate GCC installation: /usr/lib/gcc/i686-linux-gnu/6.2.0
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/5
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/5.4.1
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/6
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/6.2.0
Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/6.2.0
Candidate multilib: .;@m64
Candidate multilib: 32;@m32
Candidate multilib: x32;@mx32
Selected multilib: .;@m64
INFO:root:(Emscripten: Running sanity checks)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions