工作上需要前端实现扫描二维码的功能,这部分属于图像识别的工作,图像识别相关的库基本都是 C 语言库,所以需要将这些库编译到 WebAssembly,然后在前端调用。
胶水函数
我们需要将 C 语言的函数暴露出来,这样前端才能调用这些函数,这部分代码称为胶水函数。下面列举了一个简单的例子。
#include <emscripten.h>
#include <zbar.h>
#include <stdio.h>
#include <stdlib.h>
#define EXPORT EMSCRIPTEN_KEEPALIVE
typedef int int32_t;
typedef unsigned int uint32_t;
EXPORT zbar_image_scanner_t* ImageScanner_create() {
return zbar_image_scanner_create();
}
1
2
3
4
5
6
7
8
9
10
11
12
编写 Makefile
ZBAR_VERSION = 0.23.90
ZBAR_SRC = zbar-$(ZBAR_VERSION)
SRC = src
BUILD = build
DIST = dist
EM_VERSION = 3.1.44
EMCC = emcc
EMMAKE = emmake
EMCONFIG = emconfigure
ZBAR_DEPS = $(ZBAR_SRC)/make.done
ZBAR_OBJS = $(ZBAR_SRC)/zbar/*.o $(ZBAR_SRC)/zbar/*/*.o
ZBAR_INC = -I $(ZBAR_SRC)/include/ -I $(ZBAR_SRC)/
EMCC_FLAGS = -Oz -Wall -Werror -s ALLOW_MEMORY_GROWTH=1 \
-s EXPORTED_FUNCTIONS="['_malloc','_free']" \
-s MODULARIZE=1 -s EXPORT_NAME=zbarWasm
.PHONY: all build clean-build clean
all: build
build: $(BUILD)/zbar.js $(BUILD)/zbar.wasm
clean-build:
-rm -rf $(DIST) $(BUILD)
clean: clean-build
-rm $(ZBAR_SRC).tar.gz
-rm -rf $(ZBAR_SRC)
$(BUILD)/zbar.wasm $(BUILD)/zbar.js: $(ZBAR_DEPS) $(SRC)/export.c
mkdir -p $(BUILD)/
$(EMCC) $(EMCC_FLAGS) -o $(BUILD)/zbar.js -sEXPORT_ES6 $(SRC)/export.c $(ZBAR_INC) $(ZBAR_OBJS)
$(ZBAR_DEPS): $(ZBAR_SRC)/Makefile
cd $(ZBAR_SRC) && $(EMMAKE) make CFLAGS=-Os CXXFLAGS=-Os \
DEFS="-DZNO_MESSAGES -DHAVE_CONFIG_H"
touch -m $(ZBAR_DEPS)
$(ZBAR_SRC)/Makefile: $(ZBAR_SRC)/configure
cd $(ZBAR_SRC) && $(EMCONFIG) ./configure --without-x --without-xshm \
--without-xv --without-jpeg --without-libiconv-prefix \
--without-imagemagick --without-npapi --without-gtk \
--without-python --without-qt --without-xshm --disable-video \
--disable-pthread --disable-assert --host=x86_64-linux-gnu
$(ZBAR_SRC)/configure: $(ZBAR_SRC).tar.gz
tar zxvf $(ZBAR_SRC).tar.gz
touch -m $(ZBAR_SRC)/configure
$(ZBAR_SRC).tar.gz:
curl -L -o $(ZBAR_SRC).tar.gz https://linuxtv.org/downloads/zbar/zbar-$(ZBAR_VERSION).tar.gz
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
Makefile 中定义了编译 zbar 的流程,我们首先使用 curl 下载 zbar 的源码,然后解压,然后配置编译参数,最后编译生成 zbar 的调用 JS 和 WASM 文件。注意在配置参数中我们禁用了一些功能,因为这些功能在 WebAssembly 中不需要,并且在指定 host 的时候需要根据运行环境设置正确的参数,如果是运行在 Github Actions 中,需要设置为 x86_64-linux-gnu
。如果是 M1 芯片的 Mac,需要设置为 arm
。
函数封装
虽然我们从 zbar 暴露出来关键的图像处理相关的函数,但是用起来还不是那么方便,所以我们需要写一点 Typescript 的代码来封装这些函数。然后使用 rollup 打包成 JS 文件,并生成对应的 TS 类型文件。这部分实现细节就不赘述了。
总结
编译 zbar 到 WebAssembly 的过程并不复杂,但是需要注意一些细节,比如编译参数的设置,胶水函数的编写等。这部分工作需要一定的 C 语言基础,如果没有的话,可以参考一些现成的例子,然后根据自己的需求进行修改。我也是参考网上的例子,然后根据自己的需求进行修改的。
参考
undecaf/zbar-wasm (opens new window)
acgotaku/zbar-wasm (opens new window)