WebAssembly技术让前端能写出高性能代码,但对于习惯写C++代码的人员来说,生成的javascript代码没有智能提示,没有类型检查,写代码就变的非常痛苦,大部分时间都花费在调试上,工作效率很低,让人在WebAssembly技术上望而却步。 好在最新的emsdk已经支持了typescript
,对于习惯了强类型语言的人来说非常友好。然目前网上这方面的资料太少了,本文也是摸索了很久才验证成功。字少都是干货。
环境要求
- emsdk版本 3.1.69 (在此之前的版本在测试过程中发现比较多的问题,不建议)
- typescript 4.5.5
- nodejs 18.18.0 (可以使用nvm 管理)
C++工程
使用emcmake编译,方便大项目管理
cmake_minimum_required(VERSION 3.10)
project(example)
add_executable(example main.cpp)
set_target_properties(example PROPERTIES LINK_FLAGS "-lembind -s EXPORTED_FUNCTIONS=['_malloc','_free'] --emit-tsd=example.d.ts -sEXPORT_ES6")
#include <emscripten.h>
#include <emscripten/bind.h>
using namespace emscripten;
class Example {
public:
int add(int a, int b) {
return a + b;
}
};
EMSCRIPTEN_BINDINGS(emcadlib){
class_<Example>("Example")
.constructor<>()
.function("add", &Example::add);
}
编译工程
mkdir build
cd build
emcmake cmake ..
emmake make
执行结果
其中d.ts文件内容如下:
declare namespace RuntimeExports {
let HEAPF32: any;
let HEAPF64: any;
let HEAP_DATA_VIEW: any;
let HEAP8: any;
let HEAPU8: any;
let HEAP16: any;
let HEAPU16: any;
let HEAP32: any;
let HEAPU32: any;
let HEAP64: any;
let HEAPU64: any;
}
interface WasmModule {
_malloc(_0: number): number;
_free(_0: number): void;
}
export interface Example {
add(_0: number, _1: number): number;
delete(): void;
}
interface EmbindModule {
Example: {
new(): Example;
};
}
export type MainModule = WasmModule & typeof RuntimeExports & EmbindModule;
export default function MainModuleFactory (options?: unknown): Promise<MainModule>;
如果出现tsc not found 的错误,则需要安装tsc
npm install -g typescript
vue 工程
npm install -g @vue/cli
vue create vue1
在vue中添加执行代码.
<template>
<div>
<button @click="handleClick">点击我</button>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
//我将example.js,example.d.ts放在了这个目录
import Module from '../utils/example'
export default defineComponent({
name: 'MyComponent',
setup() {
const handleClick = async () => {
//这段代码之前纠结了很久才成功,一开始生成的js代码不是es6版本的,导致了各种小问题.
const module = await Module();
let new_example=new module.Example();
console.log(new_example.add(2,3));
};
return { handleClick };
},
});
</script>
vue的目录结构
example.wasm文件我放在了两个地方,一个在public/js目录下,一个在utils目录下(和js文件同目录),只放一个地方好像会报错,没有细究原因。