如何打开大于 4KB 的侧模块?
How to dlopen a side module larger than 4KB?
我正在尝试使用 dlopen()
从主模块动态加载辅助模块。
只要小于 4KB 的侧模块就可以正常加载,但我需要加载大尺寸的侧模块。
这是您可以测试的简单代码:
side.c:
#define SIZE 4000
char dummy[SIZE] = {};
int side(int a)
{
return SIZE;
}
main.c:
#include <stdio.h>
#include <dlfcn.h>
int main()
{
void *handle;
typedef int (*func_t)(int);
handle = dlopen("side.wasm", RTLD_NOW);
if (!handle) {
printf("failed to open the library\n");
return 0;
}
func_t func = (func_t)dlsym(handle, "side");
if (!func) {
printf("failed to find the method\n");
dlclose(handle);
return 0;
}
printf("side module size: %d byte\n", func(1));
}
index.html:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script async src="main.js"></script>
</body>
</html>
命令:
emcc side.c -s SIDE_MODULE=1 -o side.wasm
emcc main.c -s MAIN_MODULE=1 -o main.html --preload-file side.wasm
python3 -m http.server 8080
这是我在 Chrome 浏览器中得到的结果:
Error in loading dynamic library side.wasm: RangeError: WebAssembly.Compile is disallowed on the main thread, if the buffer size is larger than 4KB. Use WebAssembly.compile, or compile on a worker thread.
有人可以指导我如何动态加载大于 4KB 的侧模块吗?
我找到了一个替代解决方案,它使用 loadDynamicLibrary()
和 Asyncify
而不是 dlopen()
。
这是完整的示例代码:
main.c:
#include <stdio.h>
#include <emscripten.h>
EM_JS(void, doLoadLibrary, (), {
Asyncify.handleAsync(async() => {
try {
await loadDynamicLibrary('side.wasm', { loadAsync: true, global: true, nodelete: true, fs: FS });
console.log('side module size: ' + Module['_side']());
}
catch (error) {
console.log(error);
}
});
});
EMSCRIPTEN_KEEPALIVE
void loadLibrary() {
printf("before\n");
doLoadLibrary();
printf("after\n");
}
int main()
{
}
side.c:
#define SIZE 5000
char dummy[SIZE] = {};
int side(void)
{
return SIZE;
}
index.html:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<input id="uploadLibrary" type="file" />
<button id="loadLibrary">loadLibrary</button>
<script>
function uploadLibrary() {
var files = this.files;
if (files.length === 0) {
console.log("No file is selected");
return;
}
var file = files[0];
var reader = new FileReader();
reader.onload = function () {
var data = new Uint8Array(reader.result);
Module["FS_createDataFile"]("/", file.name, data, true, true, true);
};
reader.readAsArrayBuffer(file);
}
function loadLibrary() {
Module._loadLibrary();
}
document.getElementById("uploadLibrary").addEventListener("change", uploadLibrary, false);
document.getElementById("loadLibrary").addEventListener("click", loadLibrary, false);
</script>
<script async src="main.js"></script>
</body>
</html>
生成文件:
all: clean
mkdir -p side
emcc side.c -s SIDE_MODULE=1 -o side/side.wasm
emcc main.c -s MAIN_MODULE=1 -s ASYNCIFY -s "ASYNCIFY_IMPORTS=['doLoadLibrary']" -s FORCE_FILESYSTEM=1 -s "EXTRA_EXPORTED_RUNTIME_METHODS=['FS']" -o main.html
python3 -m http.server 8080
clean:
rm -rf side main.html main.js main.wasm main.data
在您的浏览器中,单击“选择文件”和select side/side.wasm
文件,然后单击“加载库”按钮。
您将在控制台中看到以下结果:
before
side module size: 5000
after
我正在尝试使用 dlopen()
从主模块动态加载辅助模块。
只要小于 4KB 的侧模块就可以正常加载,但我需要加载大尺寸的侧模块。
这是您可以测试的简单代码:
side.c:
#define SIZE 4000
char dummy[SIZE] = {};
int side(int a)
{
return SIZE;
}
main.c:
#include <stdio.h>
#include <dlfcn.h>
int main()
{
void *handle;
typedef int (*func_t)(int);
handle = dlopen("side.wasm", RTLD_NOW);
if (!handle) {
printf("failed to open the library\n");
return 0;
}
func_t func = (func_t)dlsym(handle, "side");
if (!func) {
printf("failed to find the method\n");
dlclose(handle);
return 0;
}
printf("side module size: %d byte\n", func(1));
}
index.html:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script async src="main.js"></script>
</body>
</html>
命令:
emcc side.c -s SIDE_MODULE=1 -o side.wasm
emcc main.c -s MAIN_MODULE=1 -o main.html --preload-file side.wasm
python3 -m http.server 8080
这是我在 Chrome 浏览器中得到的结果:
Error in loading dynamic library side.wasm: RangeError: WebAssembly.Compile is disallowed on the main thread, if the buffer size is larger than 4KB. Use WebAssembly.compile, or compile on a worker thread.
有人可以指导我如何动态加载大于 4KB 的侧模块吗?
我找到了一个替代解决方案,它使用 loadDynamicLibrary()
和 Asyncify
而不是 dlopen()
。
这是完整的示例代码:
main.c:
#include <stdio.h>
#include <emscripten.h>
EM_JS(void, doLoadLibrary, (), {
Asyncify.handleAsync(async() => {
try {
await loadDynamicLibrary('side.wasm', { loadAsync: true, global: true, nodelete: true, fs: FS });
console.log('side module size: ' + Module['_side']());
}
catch (error) {
console.log(error);
}
});
});
EMSCRIPTEN_KEEPALIVE
void loadLibrary() {
printf("before\n");
doLoadLibrary();
printf("after\n");
}
int main()
{
}
side.c:
#define SIZE 5000
char dummy[SIZE] = {};
int side(void)
{
return SIZE;
}
index.html:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<input id="uploadLibrary" type="file" />
<button id="loadLibrary">loadLibrary</button>
<script>
function uploadLibrary() {
var files = this.files;
if (files.length === 0) {
console.log("No file is selected");
return;
}
var file = files[0];
var reader = new FileReader();
reader.onload = function () {
var data = new Uint8Array(reader.result);
Module["FS_createDataFile"]("/", file.name, data, true, true, true);
};
reader.readAsArrayBuffer(file);
}
function loadLibrary() {
Module._loadLibrary();
}
document.getElementById("uploadLibrary").addEventListener("change", uploadLibrary, false);
document.getElementById("loadLibrary").addEventListener("click", loadLibrary, false);
</script>
<script async src="main.js"></script>
</body>
</html>
生成文件:
all: clean
mkdir -p side
emcc side.c -s SIDE_MODULE=1 -o side/side.wasm
emcc main.c -s MAIN_MODULE=1 -s ASYNCIFY -s "ASYNCIFY_IMPORTS=['doLoadLibrary']" -s FORCE_FILESYSTEM=1 -s "EXTRA_EXPORTED_RUNTIME_METHODS=['FS']" -o main.html
python3 -m http.server 8080
clean:
rm -rf side main.html main.js main.wasm main.data
在您的浏览器中,单击“选择文件”和select side/side.wasm
文件,然后单击“加载库”按钮。
您将在控制台中看到以下结果:
before
side module size: 5000
after