如何将外部 C 库链接到 WebAssembly 构建 [英] How Link External C Library to WebAssembly Build

查看:39
本文介绍了如何将外部 C 库链接到 WebAssembly 构建的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读这篇文章(https://www.smashingmagazine.com/2019/04/webassembly-speed-web-app/),解释了他们如何使用 zlib 等来加速他们的网络项目:

I was reading this article (https://www.smashingmagazine.com/2019/04/webassembly-speed-web-app/) that explained how they used zlib, among other things, to speed up their web project:

为了支持 zlib 库,我们使用标志 USE_ZLIB;zlib 是如此普遍以至于它已经被移植到 WebAssembly,并且 Emscripten 会在我们的项目中为我们包含它

To support the zlib library, we use the flag USE_ZLIB; zlib is so common that it’s already been ported to WebAssembly, and Emscripten will include it for us in our project

我想在我自己的 WASM 模块中使用 zlib.

I would like to use zlib in my own WASM module.

在我的 C 代码(用 emcc 编译)中,我写了这个接口函数:

In my C code (compiled with emcc), I wrote this interfacing function:

#include <zlib.h>

int pcf_decompress_zlib(unsigned char *input, int input_length, unsigned char *output, int output_length)
{
    uLongf output_length_result = output_length;
    int result = uncompress(output, &output_length_result, input, input_length);
    if (result != Z_OK) {
        return 0;
    } else {
        return output_length_result;
    }
}

我是这样编译的:

emcc decompress.c -O3 -s WASM=1 -s SIDE_MODULE=1 -s "EXPORTED_FUNCTIONS=['_pcf_decompress_zlib']" -s USE_ZLIB=1 -o decompress.wasm

当我这样做时,emcc 自动下载到一个 zlib 库中,所以它似乎知道如何处理.

When I did that, emcc automatically downloaded in a zlib library, so it seemed to know how to handle this.

然后在浏览器中,我有这个类:

Then in the browser, I have this class:

export class Decompressor {
    wasmOnLoad(obj) {
        this.instance = obj.instance;
        console.log("Loaded WASM");
        console.log(obj.instance);
        // Don't do anything else yet
    }

    constructor() {
        this.memory = new WebAssembly.Memory({
            initial: 1
        });
        this.heap = new Uint8Array(this.memory.buffer);
        this.imports = {
            env: {
                __memory_base: 0,
                memory: this.memory,
                abort: function(err) {
                    throw new Error('abort ' + err);
                },
            }
        };
    }

    start() {
        console.log("startWasm");
        WebAssembly.instantiateStreaming(fetch('decompress/decompress.wasm'), this.imports)
            .then(this.wasmOnLoad.bind(this));
    }
}

然后这是从我的 HTML 加载的主要 JS 代码:

And then this in my main JS code loaded from my HTML:

import { Decompressor } from "./decompress/decompress.js";
var l = new Decompressor();
l.start();

当我加载页面时,Firefox 给了我这个错误:

When I load the page, Firefox gives me this error:

LinkError: import object field '_uncompress' is not a Function

似乎发出的 wasm 代码不包含 zlib,并且 zlib 也未内置到浏览器中.本来想把SIDE_MODULE改成MAIN_MODULE,结果有几十个未定义的符号,问题更严重.

It appears that the wasm code being emitted doesn't include zlib, and zlib is also not built into the browser. I thought about changing SIDE_MODULE to MAIN_MODULE, but that resulted in dozens of undefined symbols, making the problem even worse.

如果 emcc 没有自动使 zlib 可用,那么让 emcc 提供 USE_ZLIB=1 选项是没有意义的.那么我缺少什么才能使这项工作发挥作用?我如何让 emcc 将 它已经具有的 zlib 代码静态包含到我正在编译的 wasm 模块中?

There would be no point in having emcc provide a USE_ZLIB=1 option if it didn't automatically make zlib available. So what am I missing t make this work? How do I get emcc to statically include the zlib code that it already has into the wasm module I'm compiling?

谢谢.

推荐答案

一种方法是包含 zlib 源在 emcc 构建期间.我在下面测试过.首先创建这个文件结构(包括你下载的zlib源文件夹)

One way is to include the zlib source during the emcc build. I tested below. First, create this file structure (include the zlib source folder you downloaded)

$ tree -L 2 .
.
├── build.sh
├── dist
├── lib
│   └── zlib-1.2.11
└── src
    └── decompress.c

build.sh

ZLIB="lib/zlib-1.2.11"

emcc \
  -O3 \
  -s WASM=1 \
  -s EXPORTED_FUNCTIONS="[ \
      '_free', '_malloc' \
    , '_pcf_decompress_zlib' \
  ]" \
  -I $ZLIB \
  -o dist/decompress.wasm \
  $ZLIB/*.c \
  src/decompress.c

<小时>

现在,配置 zlib 并构建!


Now, configure zlib and build!

$ lib/zlib-1.2.11/configure  `# you only need to run this once`
$ ./build.sh

这篇关于如何将外部 C 库链接到 WebAssembly 构建的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆