本文介绍了如何从WebAssembly文本格式访问DOM?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此演示了如何从C程序访问WebAssembly中的DOM。 :

  #ifdef __EMSCRIPTEN__ 
#include< emscripten.h> ;:
#endif

unsigned int EMSCRIPTEN_KEEPALIVE IncrementClickCountOnValue()
{
//保留此函数被点击次数的静态变量
静态int clicks = 0;

//通过EM_ASM_提供的Javascript调用修改DOM,getElementById是使用的DOM API
EM_ASM_({document.getElementById( run)。value ='Webassembly点击计数:'+ $ 0},++ clicks);
返回1;
}

如果您进行编译( emcc dom.c -O1 -s MODULARIZE = 1 -s WASM = 1 -o dom.js )并运行它( emrun --no_browser --port 8080。



如果没有C,我该怎么办? e。相当于 EM_ASM_({document.getElementById( run)。value ='Webassembly点击计数:'+ $ 0},++ clicks);

解决方案

没有纯粹的WebAssembly文本格式的等效项,因为WebAssembly环境对DOM(或任何浏览器API)或如何操作它一​​无所知。 / p>

WebAssembly可以执行的操作是从其宿主环境(例如浏览器)导入功能。然后,您可以使用 call 指令从WebAssembly中调用这些函数,方法是提供导入的函数索引或名称。



这是一个在WebAssembly中增加静态(全局)然后根据计数更新DOM的示例:

  ;; clicks.wat 

(模块

;从JavaScript地

导入updateClickCount函数(导入按钮 updateClickCount
) (func $ updateClickCount
(参数$ x i32)



;;定义一个初始化为0

的可变静态i32 (全局$ count(mut i32)(i32.const 0))

;;定义并导出一个函数到JS land

(func(导出 onClick)

;;增加全局计数

get_global $ count
i32.const 1
i32.add
set_global $ count

;;将计数压入堆栈,并调用导入的函数

get_global $ count
调用$ updateClickCount


这可能是相应的HTML / JS,用于加载和设置导入并连接到DOM:

 <!DOCTYPE html> 
< html lang = zh-CN>
< head>
< meta charset = UTF-8>
< meta name = viewport content = width = device-width,initial-scale = 1.0>
<元http-equiv = X-UA-Compatible content = ie = edge>
< title> Clicks< / title>
< / head>
< body>

< button id = click>点击我< / button>
< p id = numclicks>< / p>

< script>

//这就是我们将提供给wasm

const进口= {
按钮:{
updateClickCount:(num)=> ; document.getElementById('numclicks')。innerHTML = num.toString()
}
};

WebAssembly.instantiateStreaming(fetch('clicks.wasm'),导入)
.then(obj => {

const export = obj.instance。出口;

//单击按钮时,在wasm中调用函数

document.getElementById('click')。addEventListener('click',()=> ; {{

exports.onClick();
});

})。catch((err)=> console.error(err));
< / script>
< / body>
< / html>

WebAssembly工作室示例(单击生成并运行):


This article demonstrates how to access the DOM in WebAssembly from a C program:

#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif

unsigned int EMSCRIPTEN_KEEPALIVE IncrementClickCountOnValue()
{
    // Static variable that hold how many times this function was clicked
    static int clicks=0;

    // Modify the DOM, through a Javascript call provided by EM_ASM_, getElementById  is the DOM API used
    EM_ASM_( {document.getElementById("run").value='Webassembly click count: '+$0}, ++clicks );
    return 1;
}

If you compile (emcc dom.c -O1 -s MODULARIZE=1 -s WASM=1 -o dom.js) and run it (emrun --no_browser --port 8080 .), it works as expected.

How can I do the same without C, i. e. what would be the equivalent of EM_ASM_( {document.getElementById("run").value='Webassembly click count: '+$0}, ++clicks ); in the WebAssembly text format?

解决方案

There's no equivalent purely in WebAssembly text format because the WebAssembly environment doesn't know anything about the DOM (or any of the browser APIs) or how to manipulate it.

What WebAssembly can do though is import functions from its host environment, such as the browser. You can then call those functions from within WebAssembly using the call instruction by providing the imported function index or by a name.

Here's an example of incrementing a static (global) in WebAssembly and then updating the DOM based on the count:

;; clicks.wat

(module

    ;; import the updateClickCount function from JavaScript land

    (import "button" "updateClickCount"
        (func $updateClickCount
            (param $x i32)
        )
    )

    ;; Define a mutable static i32 initialized at 0

    (global $count (mut i32) (i32.const 0))

    ;; Define and export a function to JS land

    (func (export "onClick")

        ;; Increment the global count

        get_global $count
        i32.const 1
        i32.add
        set_global $count

        ;; Push the count on the stack and call the imported function

        get_global $count
        call $updateClickCount
    )
)

This might be the corresponding HTML/JS to load and set the imports and hook up to the DOM:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Clicks</title>
</head>
<body>

    <button id="click">CLICK ME</button>
    <p id="numclicks"></p>

    <script>

        // This is what we'll make available to wasm

        const imports = {
            button: {
                updateClickCount: (num) => document.getElementById('numclicks').innerHTML = num.toString()
            }
        };

        WebAssembly.instantiateStreaming(fetch('clicks.wasm'), imports)
            .then(obj => {

                const exports = obj.instance.exports;

                // When the button is clicked, call the function in wasm

              document.getElementById('click').addEventListener('click', () => {

                    exports.onClick();
                });

            }).catch((err) => console.error(err));
    </script>
</body>
</html>

WebAssembly studio example (click build and run): https://webassembly.studio/?f=ff0fei4xgd9

这篇关于如何从WebAssembly文本格式访问DOM?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

06-19 15:32