亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何從WebAssembly函數返回JavaScript字符串

如何從WebAssembly函數返回JavaScript字符串

郎朗坤 2019-11-30 13:58:43
如何從WebAssembly函數返回JavaScript字符串?下列模塊可以用C(++)編寫嗎?export function foo() {  return 'Hello World!';}另外:我可以將其傳遞給JS引擎進行垃圾回收嗎?
查看完整描述

3 回答

?
蝴蝶刀刀

TA貢獻1801條經驗 獲得超8個贊

WebAssembly本身不支持字符串類型,它,而支撐件i32/ i64/ f32/ f64 值類型以及i8/ i16用于存儲。


您可以使用以下方法與WebAssembly實例進行交互:


exports,您可以從JavaScript中調用WebAssembly,然后WebAssembly返回單個值類型。

imports 其中WebAssembly調用JavaScript,并具有所需的任意數量的值類型(注意:必須在模塊編譯時知道計數,這不是數組,也不是可變參數)。

Memory.buffer,ArrayBuffer可以使用(以及其他)索引Uint8Array。

這取決于您要執行的操作,但似乎直接訪問緩沖區是最簡單的:


const bin = ...; // WebAssembly binary, I assume below that it imports a memory from module "imports", field "memory".

const module = new WebAssembly.Module(bin);

const memory = new WebAssembly.Memory({ initial: 2 }); // Size is in pages.

const instance = new WebAssembly.Instance(module, { imports: { memory: memory } });

const arrayBuffer = memory.buffer;

const buffer = new Uint8Array(arrayBuffer);

如果您的模塊具有start功能,那么它將在實例化時執行。否則,您可能會調用一個導出,例如instance.exports.doIt()。


完成后,您需要獲取字符串大小+內存中的索引,您還可以通過導出將其公開:


const size = instance.exports.myStringSize();

const index = instance.exports.myStringIndex();

然后,將其從緩沖區中讀取:


let s = "";

for (let i = index; i < index + size; ++i)

  s += String.fromCharCode(buffer[i]);

請注意,我正在從緩沖區讀取8位值,因此我假設字符串是ASCII。那就是std::string給你的東西(內存中的索引就是.c_str()返回的東西),但是要暴露其他東西(例如UTF-8),您需要使用支持UTF-8的C ++庫,然后自己從JavaScript中讀取UTF-8,獲得代碼點,然后使用String.fromCodePoint。


您還可以依靠以null終止的字符串,我在這里沒有這樣做。


您也可以使用TextDecoderAPI,一旦它獲得更廣泛的瀏覽器中創建一個ArrayBufferView到WebAssembly.Memory的buffer(這是ArrayBuffer)。


相反,如果您正在執行從WebAssembly到JavaScript的日志記錄等操作,則可以公開Memory上述內容,然后從WebAssembly聲明一個導入,該導入以size + position調用JavaScript。您可以將模塊實例化為:


const memory = new WebAssembly.Memory({ initial: 2 });

const arrayBuffer = memory.buffer;

const buffer = new Uint8Array(arrayBuffer);

const instance = new WebAssembly.Instance(module, {

    imports: {

        memory: memory,

        logString: (size, index) => {

            let s = "";

            for (let i = index; i < index + size; ++i)

                s += String.fromCharCode(buffer[i]);

            console.log(s);

    }

});

需要注意的是,如果您增加了內存(通過使用JavaScript的JavaScript Memory.prototype.grow或使用grow_memory操作碼),則內存將ArrayBuffer被清除,您需要重新創建。


垃圾收集器:WebAssembly.Module/ WebAssembly.Instance/ WebAssembly.Memory是由JavaScript引擎收集到的所有垃圾,但是這是一個相當大的錘子。您可能希望使用GC字符串,而對于位于中的對象,目前尚無法實現WebAssembly.Memory。我們已經討論了將來增加GC支持的問題。


查看完整回答
反對 回復 2019-11-30
?
哆啦的時光機

TA貢獻1779條經驗 獲得超6個贊

有一種更簡單的方法可以做到這一點。首先,您需要二進制文件的實例:


const module = new WebAssembly.Module(bin);

const memory = new WebAssembly.Memory({ initial: 2 });

const instance = new WebAssembly.Instance(module, { imports: { memory: memory } });

然后,如果運行console.log(instance),則幾乎在該對象的頂部,您將看到function AsciiToString。從C ++傳遞您的函數,該函數返回字符串,您將看到輸出。對于這種情況,請查看此庫。


查看完整回答
反對 回復 2019-11-30
  • 3 回答
  • 0 關注
  • 803 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號