飞万达吊运机-600261股份股吧

WebAssembly编程实践(1.3)胶水代码初探
2023年9月26日发(作者:武光汤)

WebAssembly编程实践(1.3)胶⽔代码初探

说明:本系列⽂章转载⾃《C/C++⾯向wasm编程——Emscripten⼯程实践》系列教程(名字太长,转载以《WebAssembly编程实践》

为题)。

作者:丁尔男,Github @3dgen

作者:柴树杉,Github @chai2010,Twitter @chaishushan

-----------------------------------------------------------------------------------------

1.3 胶⽔代码初探

打开上⼀节(1.2)中由Emscripten⽣成的JavaScript胶⽔代码,我们可以发现,⼤多数的操作,都围绕全局对象Module展开,⽽

该对象正是Emscripten程序运⾏时的核⼼所在。

tips 跳过1.3.1以及1.3.2不会影响后续章节的阅读。但如果您对Emscripten模块载⼊等细节感兴趣,本节内容将有助于理解胶⽔代

码的结构。随着Emscripten的版本升级,其⽣成的胶⽔代码有可能发⽣变化,本节展⽰的代码均基于Emscripten 1.38.11。

1.3.1 WebAssembly汇编模块载⼊

WebAssembly汇编模块(既.wasm⽂件)的载⼊是在doNativeWasm函数中完成的。其核⼼部分如下:

function instantiateArrayBuffer(receiver) {

getBinaryPromise().then(function(binary) {

return tiate(binary, info);

}).then(receiver).catch(function(reason) {

err('failed to asynchronously prepare wasm: ' + reason);

abort(reason);

});

}

// Prefer streaming instantiation if available.

if (!Module['wasmBinary'] &&

typeof tiateStreaming === 'function' &&

!isDataURI(wasmBinaryFile) &&

typeof fetch === 'function') {

function receiveInstance(instance, module) {

exports = s;

if () mergeMemory();

Module['asm'] = exports;

Module["usingWasm"] = true;

removeRunDependency('wasm-instantiate');

}

......

function receiveInstantiatedSource(output) {

// 'output' is a WebAssemblyInstantiatedSource object which has both the module and instance.

// receiveInstance() will swap in the exports (to ) so they can be called

assert(Module === trueModule, 'the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?');

... ...

var _main = Module["_main"] = function() {

assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');

assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');

return Module["asm"]["_main"].apply(null, arguments) };

var _malloc = Module["_malloc"] = function() {

assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)');

assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)');

return Module["asm"]["_malloc"].apply(null, arguments) };

... ...

在Emscripten中,C函数导出时,函数名前会添加下划线“_”,由此可知上述代码分别提供了main()以及malloc()函数的封装;⽽var

_main以及Module._main对应的,都是中的main()函数。我们可以在浏览器控制台中⼿动执⾏_main()以及Module._main()对此进⾏

检验:

不出所料,⼆者都执⾏了C代码中的main()函数,输出了“你好,世界!”。

1.3.3 异步加载

WebAssembly实例是通过tiateStreaming()/tiate()⽅法创建的,⽽这两个⽅法均为异步调⽤,这

意味着.js⽂件加载完成时Emscripten的Runtime并未准备就绪。倘若我们修改,载⼊.js后⽴即执⾏Module._main()

控制台将输出以下错误信息:

Assertion failed: you need to wait for the runtime to be ready

(e.g. wait for main() to be called)

解决这⼀问题需要建⽴⼀种Runtime准备就绪时的通知机制,为此Emscripten提供了多种解决⽅案,最简单的⽅法是在main()函数中发出通知,但是对多数纯功能性的

其基本思路是在Module初始化前,向Module中注⼊⼀个名为onRuntimeInitialized的⽅法,Emscripten的Runtime就绪后,将会回调该⽅

法。在中,我们可以观察到该回调的调⽤过程:

function run(args) {

... ...

ensureInitRuntime();

新型防盗窗-株洲飞鹿高新材料技术股份有限公司

WebAssembly编程实践(1.3)胶水代码初探

更多推荐

406胶