首頁 >後端開發 >Golang >PSP 上的 Wasm TinyGo

PSP 上的 Wasm TinyGo

Susan Sarandon
Susan Sarandon原創
2024-12-29 03:23:10714瀏覽

我將首先附加 GitHub 儲存庫:wasm3-tinygo-psp。

主要議題

一段時間以來,我一直想在 PSP 上運行 Golang。

但是,原生編譯到 PSP 是不可能的(可能)。

當然,Golang 確實支援 GOARCH=mipsle,但它假設存在作業系統。如果您試圖實現這一目標,您可能必須走一條非常困難且佈滿荊棘的道路。

所以,我選了另一種方式。換句話說,方法就是使用TinyGo將其轉換為WASM。

現在,讓我們來看看實際的程式碼。

package main

import "unsafe"

//go:wasmimport debug println
func println(ptr unsafe.Pointer, len int32)

//export start
func start() {
    main()
}

func main() {
    message := "Hello, WebAssembly, from Golang!"
    println(unsafe.Pointer(unsafe.StringData(message)), int32(len(message)))
}

本質上,我們只是呼叫運行時提供的函數。這只是一個 Hello World 範例。

關於運行時

還有一個選項是在運行時使用 Rust 和 wasmi,但儘管它可以在 PPSSPP 這樣的模擬器上運行,但在實際硬體上會出現錯誤(如下面的螢幕截圖所示)。

Wasm TinyGo on PSP

我懷疑它可能與內核模式有關,但由於我最終無法解決它,所以我採取了不同的方法。

最終,C 和 Wasm3 的結合成功了。

Wasm TinyGo on PSP

關於前面程式碼中提到的println,它在運行時端的定義如下。

#define printf pspDebugScreenPrintf

static const void* host_debug_println(IM3Runtime runtime, IM3ImportContext ctx, uint64_t *stack, void *mem)
{
    uint32_t ptr = (uint32_t) stack[0];
    uint32_t length = (uint32_t) stack[1];

    uint8_t* bytes = (uint8_t*)mem + ptr;

    char buffer[256];
    if (length >= sizeof(buffer)) {
        length = sizeof(buffer)-1;
    }
    memcpy(buffer, bytes, length);
    buffer[length] = '';

    printf("%s\n", buffer);

    return NULL;
}

由於這只是一個演示,所以現在就這些了。但是,如果您也包裝其他函數並使其可從 WASM 調用,那麼您應該能夠開發成熟的應用程式。

面臨的挑戰

交叉編譯 Wasm3

需要使用PSP工具鏈編譯Wasm3。

我創建了一個fork的倉庫,方便大家搭建環境,請參考:wasm3-for-psp。

TinyGo 建置選項

最後,我得到了tinygo build -o hello.wasm -target=wasm -no-debug main.go 指令,但我花了相當多的時間才得到這樣一個簡單的指令。我還有很多東西要學。

導出主函數

如果您使用-target=wasi,TinyGo 將 main 函數匯出為 _start。但在這種情況下,我必須定義並匯出一個單獨的啟動函數。

進而...

這次我使用TinyGo將Golang程式碼編譯成WASM,但如果其他語言也可以編譯成WASM,相信也可以用類似的方法執行。我對 Golang 充滿熱情,所以如果有人可以嘗試一下,我會很高興。

僅此而已。感謝您的閱讀。

以上是PSP 上的 Wasm TinyGo的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn