最初に 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 などのエミュレータでは動作しましたが、実際のハードウェアではエラーが発生しました (下のスクリーンショットを参照)。
カーネル モードに関連しているのではないかと考えていますが、最終的には解決できなかったので、別のアプローチをとりました。
最終的に、C と Wasm3 の組み合わせは正常に機能しました。
先ほどのコードで触れた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 から呼び出せるようにすれば、本格的なアプリケーションを開発できるはずです。
PSP ツールチェーンを使用して Wasm3 をコンパイルする必要がありました。
誰でも簡単に環境構築できるようにフォークしたリポジトリを作成しましたので、参考までにご覧ください: wasm3-for-psp.
最終的には 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 中国語 Web サイトの他の関連記事を参照してください。