malloc () и free () в Go (WebAssembly) - PullRequest
0 голосов
/ 23 мая 2019

Я хочу предоставить память, чтобы поделиться с Javascript.В C и Rust есть malloc () и free () (для Rust это предоставляет wbindgen).Я не мог найти что-то подобное в Go?Как я могу зарезервировать память, получить указатель на нее и освободить ее после использования?

Пример использования.Сделайте что-нибудь с растровым изображением (Javascript):

const context = canvas.getContext("2d");
const size = canvas.width * canvas.height * 4;
// allocate memory in Go
const ptr = window.wasm.go.malloc(size);
const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
const dataGo = new Uint8ClampedArray(window.wasm.goMem.buffer, ptr, size);
const imageDataGo = new ImageData(dataGo, canvas.width, canvas.height);
imageDataGo.data.set(imageData.data);
// run function in Go using the pointer to the memory
window.wasm.go.convolve_mem(ptr, canvas.width, canvas.height);
context.putImageData(imageDataGo, 0, 0);
// free the memory
window.wasm.go.free(size);

Я попробовал это (Go):

exports["malloc"] = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
    size := args[0].Int()
    mem := make([]byte, size)
    ptr := uintptr(unsafe.Pointer(&mem))
    return uint64(ptr)
})

make должен инициализировать все элементы массива байтов с 0. Нов JS я получаю случайный массив.Поэтому я предполагаю, что это не работает, как ожидалось.Я также предполагаю, что сборщик мусора освобождает память сразу после возврата функции.

Как зарезервировать память в Go, как я могу это сделать в C?


go версия go1.12.1Linux / amd64

1 Ответ

0 голосов
/ 23 мая 2019

Я не нашел решения в Go, но я могу использовать другие модули Wasm с той же памятью Wasm.В CI можно использовать malloc и есть модуль Wasm.См. Комментарии к коду.

const go = new window.Go();

// use the same WASM memory for all Wasm instances
const memory = new WebAssembly.Memory({initial: 1024});

Promise.all([
    // The main WASM module with my photo filter
    WebAssembly.instantiateStreaming(fetch('some-go-wasm-module.wasm'), {
        env: {memory},
        ...go.importObject
    }),
    // the memory library written in C provides: abort, calloc, free, malloc, memcoy, memset, sbrk
    // source: https://github.com/guybedford/wasm-stdlib-hack/blob/master/dist/memory.wasm
    WebAssembly.instantiateStreaming(fetch("memory.wasm"), {
        env: {memory}
    })
])
    .then(module => {
        go.run(module[0].instance);
        window.wasm.memHelper = {
            memory,
            ...module[1].instance.exports
        };
    });

Теперь я могу выделять и освобождать память и обращаться к ней в функциях Go с помощью указателя.Этот пример из другого вопроса - чтобы показать, как это работает:

const context = canvas.getContext("2d");
const size = canvas.width * canvas.height * 4;

// allocate memory for the image bitmap
const ptr = window.wasm.memHelper.malloc(size);

const imageData = context.getImageData(0, 0, canvas.width, canvas.height);

// create a new ImageData object from this memory
const dataGo = new Uint8ClampedArray(window.wasm.memHelper.memory.buffer, ptr, size);
const imageDataGo = new ImageData(dataGo, canvas.width, canvas.height);

// copy the image from JS context to the WASM context
imageDataGo.data.set(imageData.data);

// run my Go filter
window.wasm.go.convolve_mem(ptr, canvas.width, canvas.height);

// copy the image bitmap from Wasm context back to the canvas
context.putImageData(imageDataGo, 0, 0);

// free memory
window.wasm.memHelper.free(ptr);
...