# 数组示例
展示了如何在 WebAssembly 或 JavaScript 中创建的数组之间交换和操作数组。
# 内容
- 使用加载器和完整运行时来处理托管对象。
- 在 WebAssembly 中创建数组并在 JavaScript 中使用它们。
- 在 JavaScript 中创建数组并在 WebAssembly 中使用它们。
- 同时使用数组的副本和实时视图。
- 在已知数组长度的情况下执行 `unchecked` 访问。
- 外部固定对象以防止过早垃圾回收。
# 示例
#!optimize=speed&runtime=default&exportRuntime
/** Creates a new array and returns it to JavaScript. */
export function createArray(length: i32): Int32Array {
return new Int32Array(length)
}
/** Randomizes the specified array's values. */
export function randomizeArray(arr: Int32Array): void {
for (let i = 0, k = arr.length; i < k; ++i) {
let value = i32((Math.random() * 2.0 - 1.0) * i32.MAX_VALUE)
unchecked(arr[i] = value)
}
}
/** Computes the sum of an array's values and returns the sum to JavaScript. */
export function sumArray(arr: Int32Array): i32 {
let total = 0
for (let i = 0, k = arr.length; i < k; ++i) {
total += unchecked(arr[i])
}
return total
}
// We'll need the unique Int32Array id when allocating one in JavaScript
export const Int32Array_ID = idof<Int32Array>()
#!html
<textarea id="output" style="width: 100%; height: 100%" readonly></textarea>
<script>
loader.instantiate(module_wasm).then(({ exports }) => {
const output = document.getElementById('output')
/** Logs a message to the textarea. */
function log(message = '') {
output.value += `${message}\n`
}
// A simple example using an array created in WebAssembly.
function example1() {
log('=== Example1 ===')
// Obtain the necessary runtime helpers
const { __pin, __unpin, __getArray } = exports
// Create a new array in WebAssembly and get a reference to it. Note that
// the array is not reachable from within WebAssembly, only externally, so
// we should pin it to prevent it from becoming garbage collected too early.
let arrayPtr = __pin(exports.createArray(5))
log(`Array pointer: ${arrayPtr}`)
// Log its elements to make sure these are zero
log('Initial values: ' + __getArray(arrayPtr).join(', '))
// Randomize the array in WebAssembly and log it again
exports.randomizeArray(arrayPtr)
log('Randomized values: ' + __getArray(arrayPtr).join(', '))
// Compute the array values' sum and log it. This will overflow i32 range.
let total = exports.sumArray(arrayPtr)
log(`Sum (likely overflown): ${total}`)
// We are done with the array, so __unpin it so it can become collected.
__unpin(arrayPtr)
log()
}
example1()
// A slightly more advanced example allocating the array in JavaScript instead
// of WebAssembly, and utilizing a live view to modify it in WebAssembly memory.
function example2() {
log('=== Example2 ===')
// Obtain the necessary runtime helpers
const { __pin, __unpin, __newArray, __getArray, __getArrayView } = exports
// Create a new array, but this time in JavaScript. Note that the array is
// again not reachable from within WebAssembly, only externally, so we
// should pin it to prevent it from becoming garbage collected too early.
let arrayPtr = __pin(__newArray(exports.Int32Array_ID, [
3, 4, 5, 6, 7, 8, 9
]))
log('Array pointer: ' + arrayPtr)
// Log its elements to make sure these are the provided values
log('Initial values: ' + __getArray(arrayPtr).join(', '))
// Compute the array values' sum and log it
let total = exports.sumArray(arrayPtr)
log('Sum: ' + total)
// Instead of copying, let's obtain a live view on the array and modify its
// values right in WebAssembly memory.
let view = __getArrayView(arrayPtr)
view.reverse()
// Log the array's elements, now reversed
log('Reversed values: ' + __getArray(arrayPtr).join(', '))
// We are done with the array, so __unpin it so it can become collected.
__unpin(arrayPtr)
log()
}
example2()
})
</script>
注意
此示例使用加载器来处理托管对象,因此需要将 `--exportRuntime` 设置为将运行时助手暴露给 JavaScript。