如何将外部C库链接到WebAssembly的构建中去

问题描述 投票:0回答:1

我在读这篇文章(https:/www.smashingmagazine.com201904webassembly-speed-web-app)中解释了他们如何使用zlib来加快他们的web项目。

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

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

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

#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库,所以它似乎知道如何处理这个问题。

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

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));
    }
}

然后这个在我的主JS代码中 从我的HTML中加载。

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

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

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

似乎正在发射的wasm代码不包括zlib 而zlib也不是浏览器的内置代码。我想过要改变 SIDE_MODULEMAIN_MODULE但这导致了几十个未定义的符号,使问题更加严重。

如果让emcc提供了一个 USE_ZLIB=1 选项,如果它没有自动使zlib可用。那么,我缺少什么来让它工作呢?我怎样才能让emcc静态地包含zlib代码呢?它已经 到我正在编译的wasm模块中?

谢谢,我读了这篇文章(https:/)。

zlib webassembly
1个回答
3
投票

一种方法是将 zlib 节目中 emcc 构建。我在下面进行了测试。 首先,创建这个文件结构(包括你下载的zlib源文件夹)

$ 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并构建!

$ lib/zlib-1.2.11/configure  `# you only need to run this once`
$ ./build.sh
© www.soinside.com 2019 - 2024. All rights reserved.