3 回答

TA貢獻(xiàn)1801條經(jīng)驗(yàn) 獲得超8個贊
WebAssembly本身不支持字符串類型,它,而支撐件i32/ i64/ f32/ f64 值類型以及i8/ i16用于存儲。
您可以使用以下方法與WebAssembly實(shí)例進(jìn)行交互:
exports,您可以從JavaScript中調(diào)用WebAssembly,然后WebAssembly返回單個值類型。
imports 其中WebAssembly調(diào)用JavaScript,并具有所需的任意數(shù)量的值類型(注意:必須在模塊編譯時知道計(jì)數(shù),這不是數(shù)組,也不是可變參數(shù))。
Memory.buffer,ArrayBuffer可以使用(以及其他)索引Uint8Array。
這取決于您要執(zhí)行的操作,但似乎直接訪問緩沖區(qū)是最簡單的:
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功能,那么它將在實(shí)例化時執(zhí)行。否則,您可能會調(diào)用一個導(dǎo)出,例如instance.exports.doIt()。
完成后,您需要獲取字符串大小+內(nèi)存中的索引,您還可以通過導(dǎo)出將其公開:
const size = instance.exports.myStringSize();
const index = instance.exports.myStringIndex();
然后,將其從緩沖區(qū)中讀取:
let s = "";
for (let i = index; i < index + size; ++i)
s += String.fromCharCode(buffer[i]);
請注意,我正在從緩沖區(qū)讀取8位值,因此我假設(shè)字符串是ASCII。那就是std::string給你的東西(內(nèi)存中的索引就是.c_str()返回的東西),但是要暴露其他東西(例如UTF-8),您需要使用支持UTF-8的C ++庫,然后自己從JavaScript中讀取UTF-8,獲得代碼點(diǎn),然后使用String.fromCodePoint。
您還可以依靠以null終止的字符串,我在這里沒有這樣做。
您也可以使用TextDecoderAPI,一旦它獲得更廣泛的瀏覽器中創(chuàng)建一個ArrayBufferView到WebAssembly.Memory的buffer(這是ArrayBuffer)。
相反,如果您正在執(zhí)行從WebAssembly到JavaScript的日志記錄等操作,則可以公開Memory上述內(nèi)容,然后從WebAssembly聲明一個導(dǎo)入,該導(dǎo)入以size + position調(diào)用JavaScript。您可以將模塊實(shí)例化為:
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);
}
});
需要注意的是,如果您增加了內(nèi)存(通過使用JavaScript的JavaScript Memory.prototype.grow或使用grow_memory操作碼),則內(nèi)存將ArrayBuffer被清除,您需要重新創(chuàng)建。
垃圾收集器:WebAssembly.Module/ WebAssembly.Instance/ WebAssembly.Memory是由JavaScript引擎收集到的所有垃圾,但是這是一個相當(dāng)大的錘子。您可能希望使用GC字符串,而對于位于中的對象,目前尚無法實(shí)現(xiàn)WebAssembly.Memory。我們已經(jīng)討論了將來增加GC支持的問題。

TA貢獻(xiàn)1779條經(jīng)驗(yàn) 獲得超6個贊
有一種更簡單的方法可以做到這一點(diǎn)。首先,您需要二進(jìn)制文件的實(shí)例:
const module = new WebAssembly.Module(bin);
const memory = new WebAssembly.Memory({ initial: 2 });
const instance = new WebAssembly.Instance(module, { imports: { memory: memory } });
然后,如果運(yùn)行console.log(instance),則幾乎在該對象的頂部,您將看到function AsciiToString。從C ++傳遞您的函數(shù),該函數(shù)返回字符串,您將看到輸出。對于這種情況,請查看此庫。
添加回答
舉報