ホームページ >バックエンド開発 >Golang >PSP 上の Golang (およびその他の言語)

PSP 上の Golang (およびその他の言語)

Linda Hamilton
Linda Hamiltonオリジナル
2025-01-03 12:33:431067ブラウズ

PSP で Golang を使用してみることにし、Clang の移植、TinyGo の使用、GopherJS を使用した Golang の JavaScript へのコンパイルなど、いくつかのアプローチを検討しました。その後、PSP 自作の Discord で aethiopicuschan という名前のユーザーに出会いました。彼は WebAssembly を使用して同じ目標を達成しようとしていました。彼の例は PPSSPP では動作しましたが、実際のハードウェアでは動作しませんでした。

とにかく、試験が近づいているため、プロジェクトを保留しなければなりませんでした。しかし、数か月後、aethiopicuschan が Golang を WASM にコンパイルし、WASM インタプリタを使用して PSP 上で実行することに成功したという記事を見つけました。
彼のアプローチでは、Wasm3 と呼ばれる Wasm インタプリタを使用してコードを実行しましたが、私にはもっと良い方法があるとわかっていました。 Wasm バイナリを C に変換する Wasm2C のようなプロジェクトについては知っていました。
興奮してこのトピックをさらに深く調べたところ、WebAssembly を移植可能な C コードにコンパイルすることに関する記事を発見しました。 w2c2 というコンパイラを使用していて、これが続編だと思われます。

何時間も CMake をいじった後、TinyGo を使用して WASI をターゲットにした実用的なサンプルを作成することができました。また、raylib-go バインディングをこの WASM-to-C プラットフォームに移植することを目的として、raylib 関数 InitWindow もラップしました (ちなみに、psp には raylib ポートがあります)。この例では、C の InitWindow 関数をコンパイルされた WASM コードに正常にバインドします。

ご覧のとおり、他の Golang コードと似ています

package main

import "time"

import rl "github.com/gen2brain/raylib-go/raylib"

func main() {

    rl.InitWindow(480, 272, "Psp test")
    for {
        time.Sleep(time.Millisecond * 16)
    }
}

しかし、rl パッケージでは C 関数をインポートしており、それに関数シグネチャも与えています。覚えておいてください。


package rl

//go:wasmimport rl InitWindow
func c_InitWindow(width int32, height int32, title string)

// InitWindow - Initialize Window and OpenGL Graphics

func InitWindow(width int32, height int32, title string) {
    c_InitWindow(width, height, title)
}

このコードを段階的に分解してみましょう。

#define __GLIBC_USE

#include <raylib.h>
#include <stdio.h>
#include <time.h>

#include <pspkernel.h>
PSP_MODULE_INFO("WasiExample", 0, 1, 0);
PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER);
#include "pspdebug.h"
#define printf pspDebugScreenPrintf

まず、psp ライブラリをインポートし、ボイラー プレートをセットアップします。また、raylib ポートもインポートします。

ここではコンパイル済みモジュール app.h をインポートしています
また、w2c2
によって提供される wasi "ランタイム" もインポートします。

// // the compiled wasm -> C code
#include "app.h"
// // wasi runtime
#include "w2c2_base.h"
#include "wasi.h"

extern wasmMemory* e_memory;  // the WASM memory.
void trap(Trap trap)
{
  fprintf(stderr, "TRAP: %s\n", trapDescription(trap));
  abort();
}

wasmMemory* wasiMemory(void* instance)
{
  return app_memory((appInstance*)instance);
}
extern char** environ;

トラップ機能はボイラープレートです。
wasiMemory 関数は、別のヘルパー関数のために私が作成したヘルパー関数です

char* getCStringFromMemory(void* memoryptr, U32 offset, U32 length)
{
  wasmMemory* memory = wasiMemory(memoryptr);
  char* str = (char*)(memory->data + offset);
  char* result = (char*)malloc(
    length + 1);  // Allocate space for the string + null terminator
  if (result == NULL) {
    fprintf(stderr, "Memory allocation failed\n");
    return NULL;
  }

  // Copy the string from WASI memory to local memory
  for (U32 i = 0; i < length; ++i) {
    result[i] = str[i];
  }
  result[length] = '<pre class="brush:php;toolbar:false">void rl__InitWindow(
  void* memoryptr, U32 width, U32 height, U32 offset, U32 length)
{
  char* title = getCStringFromMemory(memoryptr, offset, length);
  InitWindow(width, height, title);
  bool ready = IsWindowReady();
  if (ready) {
    // this will print to the psp screen.
    printf("Window was created");
  }
}

'; // Null-terminate the string return result; }

この関数が行うことは、文字列メモリ ポインタのメモリ ポインタを取得し (wasm では、メモリ オフセットと文字列の長さを渡すことで文字列を処理します)、オフセットと長さを使用して C 文字列を返すことだけです。

これは golang コードから呼び出す C 関数です。自分で定義する必要がありました。

int main(int argc, char* argv[])
{
  pspDebugScreenInit();
  appInstance i;
  appInstantiate(&i, NULL);
  if (!wasiInit(argc, argv, environ)) {
    fprintf(stderr, "failed to initialize WASI\n");
    return 1;
  }

  app__start(&i);
  appFreeInstance(&i);
  return 0;
}

トランスパイルされた wasm によって渡された引数を読み取り、raylib に渡します。


これは定型文です。ここで行っているのは、app_start() としてエクスポートされる golang コードの main 関数を実行しているだけです

Golang on PSP (and other languages)

それは動作します!

これは、psp ?エミュレータ?のスクリーンショットです。
ただし、オリジナルのハードウェアでも動作します。

質問があればコメント欄に残してください!

以上がPSP 上の Golang (およびその他の言語)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。