プラットフォームガイド

プラットフォームガイド

Zylix は 6 つのプラットフォームで動作し、それぞれネイティブ UI フレームワークを使用して本物のユーザー体験を提供します。このセクションでは、プラットフォーム固有のセットアップ、統合パターン、およびベストプラクティスを説明します。

対応プラットフォーム

プラットフォームUI フレームワーク言語バインディングビルドコマンド
Web/WASMHTML/JavaScriptJavaScriptWebAssemblyzig build wasm
iOSSwiftUISwiftC ABIzig build ios
AndroidJetpack ComposeKotlinJNIzig build android
macOSSwiftUISwiftC ABIzig build
LinuxGTK4CC ABIzig build linux
WindowsWinUI 3C#P/Invokezig build windows-x64

プラットフォーム比較

機能WebiOSAndroidmacOSLinuxWindows
UI フレームワークHTML/JSSwiftUIComposeSwiftUIGTK4WinUI 3
言語JavaScriptSwiftKotlinSwiftCC#
バインディングWASMC ABIJNIC ABIC ABIP/Invoke
最小バージョンモダンブラウザiOS 15+API 26+macOS 12+GTK 4.0+Win 10+
バンドルサイズ~50 KB~100 KB~150 KB~100 KB~80 KB~120 KB
ホットリロード

プラットフォーム別アーキテクチャ

Web/WASM アーキテクチャ

  flowchart TB
    subgraph Browser["ブラウザ"]
        subgraph JS["JavaScript (zylix.js)"]
            Load["WASM モジュールをロード"]
            DOM["DOM 操作"]
            Events["イベント転送"]
        end

        subgraph WASM["WebAssembly (zylix.wasm)"]
            VDOM1["Virtual DOM"]
            State1["状態管理"]
            Diff1["差分アルゴリズム"]
        end

        JS --> WASM
    end

ネイティブプラットフォームアーキテクチャ

  flowchart TB
    subgraph App["ネイティブアプリ"]
        subgraph UI["プラットフォーム UI<br/>(SwiftUI / Compose / GTK4 / WinUI)"]
            Render["ネイティブレンダリング"]
            PlatformEvents["プラットフォームイベント"]
            A11y["アクセシビリティ"]
        end

        subgraph Bind["バインディング層<br/>(C ABI / JNI / P/Invoke)"]
            Calls["関数呼び出し"]
            Marshal["データマーシャリング"]
        end

        subgraph Core["Zylix Core (libzylix.a)"]
            VDOM2["Virtual DOM"]
            State2["状態管理"]
            Diff2["差分アルゴリズム"]
        end

        UI --> Bind
        Bind --> Core
    end

バインディング戦略

WebAssembly (Web)

JavaScript グルーコードを使用した WASM への直接コンパイル:

// WASM モジュールをロード
const wasmModule = await WebAssembly.instantiate(wasmBuffer, {
    env: {
        js_log: (ptr, len) => console.log(readString(ptr, len)),
        js_create_element: (tag, parent) => createElement(tag, parent),
        js_set_text: (el, ptr, len) => setTextContent(el, ptr, len),
    }
});

// 初期化
wasmModule.exports.zylix_init();

// イベントをディスパッチ
function onClick(callbackId) {
    wasmModule.exports.zylix_dispatch(callbackId, 0, 0);
    render();
}

C ABI (iOS, macOS, Linux)

直接関数呼び出しによる静的ライブラリリンク:

// Swift バインディング
@_silgen_name("zylix_init")
func zylix_init() -> Int32

@_silgen_name("zylix_dispatch")
func zylix_dispatch(_ eventType: UInt32, _ payload: UnsafeRawPointer?, _ len: Int) -> Int32

@_silgen_name("zylix_get_state")
func zylix_get_state() -> UnsafePointer<ZylixState>?

// 使用例
zylix_init()
zylix_dispatch(EVENT_INCREMENT, nil, 0)
let state = zylix_get_state()?.pointee

JNI (Android)

Kotlin/Java 相互運用のための Java Native Interface:

// Kotlin バインディング
object ZylixLib {
    init {
        System.loadLibrary("zylix")
    }

    external fun init(): Int
    external fun deinit(): Int
    external fun dispatch(eventType: Int, payload: ByteArray?, len: Int): Int
    external fun getState(): ZylixState
}

// 使用例
ZylixLib.init()
ZylixLib.dispatch(EVENT_INCREMENT, null, 0)
val state = ZylixLib.getState()

P/Invoke (Windows)

.NET ソース生成相互運用:

// C# バインディング
public static partial class ZylixInterop
{
    [LibraryImport("zylix", EntryPoint = "zylix_init")]
    public static partial int Init();

    [LibraryImport("zylix", EntryPoint = "zylix_dispatch")]
    public static partial int Dispatch(uint eventType, IntPtr payload, nuint len);

    [LibraryImport("zylix", EntryPoint = "zylix_get_state")]
    public static partial IntPtr GetState();
}

// 使用例
ZylixInterop.Init();
ZylixInterop.Dispatch(EVENT_INCREMENT, IntPtr.Zero, 0);
var statePtr = ZylixInterop.GetState();

共通パターン

状態監視

各プラットフォームは状態監視を異なる方法で実装します:

// SwiftUI with ObservableObject
class ZylixStore: ObservableObject {
    @Published var state: ZylixState

    init() {
        zylix_init()
        state = zylix_get_state()!.pointee
    }

    func dispatch(_ event: UInt32) {
        zylix_dispatch(event, nil, 0)
        state = zylix_get_state()!.pointee
    }
}
// Compose with MutableState
class ZylixStore {
    var state by mutableStateOf(ZylixLib.getState())
        private set

    fun dispatch(event: Int) {
        ZylixLib.dispatch(event, null, 0)
        state = ZylixLib.getState()
    }
}
// リアクティブ状態ラッパー
class ZylixStore {
    constructor() {
        this.listeners = [];
        this.state = zylix.getState();
    }

    dispatch(event) {
        zylix.dispatch(event, null, 0);
        this.state = zylix.getState();
        this.listeners.forEach(fn => fn(this.state));
    }

    subscribe(listener) {
        this.listeners.push(listener);
        return () => this.listeners = this.listeners.filter(l => l !== listener);
    }
}
// MVVM with INotifyPropertyChanged
public class ZylixStore : INotifyPropertyChanged
{
    private ZylixState _state;

    public ZylixState State
    {
        get => _state;
        private set { _state = value; OnPropertyChanged(); }
    }

    public void Dispatch(uint eventType)
    {
        ZylixInterop.Dispatch(eventType, IntPtr.Zero, 0);
        State = Marshal.PtrToStructure<ZylixState>(ZylixInterop.GetState());
    }
}

イベント処理

ネイティブイベントを Zylix イベントに変換:

Button("インクリメント") {
    store.dispatch(EVENT_INCREMENT)
}
.buttonStyle(.borderedProminent)

TextField("テキストを入力", text: $inputText)
    .onChange(of: inputText) { newValue in
        newValue.withCString { ptr in
            zylix_dispatch(EVENT_TEXT_INPUT, ptr, newValue.count)
        }
    }
Button(onClick = { store.dispatch(EVENT_INCREMENT) }) {
    Text("インクリメント")
}

TextField(
    value = inputText,
    onValueChange = { text ->
        ZylixLib.dispatch(EVENT_TEXT_INPUT, text.toByteArray(), text.length)
        inputText = text
    }
)
button.addEventListener('click', () => {
    store.dispatch(EVENT_INCREMENT);
});

input.addEventListener('input', (e) => {
    const text = e.target.value;
    const bytes = new TextEncoder().encode(text);
    const ptr = zylix.alloc(bytes.length);
    zylix.memory.set(bytes, ptr);
    zylix.dispatch(EVENT_TEXT_INPUT, ptr, bytes.length);
    zylix.free(ptr, bytes.length);
});
private void OnIncrementClick(object sender, RoutedEventArgs e)
{
    Store.Dispatch(EVENT_INCREMENT);
}

private void OnTextChanged(object sender, TextChangedEventArgs e)
{
    var text = ((TextBox)sender).Text;
    var bytes = Encoding.UTF8.GetBytes(text);
    fixed (byte* ptr = bytes)
    {
        ZylixInterop.Dispatch(EVENT_TEXT_INPUT, (IntPtr)ptr, (nuint)bytes.Length);
    }
}

ビルド設定

クロスプラットフォームビルドスクリプト

#!/bin/bash
# build-all.sh

# すべてのプラットフォーム向けにコアをビルド
cd core

# Web/WASM
zig build wasm -Doptimize=ReleaseSmall
cp zig-out/lib/zylix.wasm ../platforms/web/

# iOS (arm64)
zig build -Dtarget=aarch64-ios -Doptimize=ReleaseFast
cp zig-out/lib/libzylix.a ../platforms/ios/

# Android (複数 ABI)
for abi in aarch64-linux-android armv7a-linux-androideabi x86_64-linux-android; do
    zig build -Dtarget=$abi -Doptimize=ReleaseFast
    cp zig-out/lib/libzylix.a ../platforms/android/app/src/main/jniLibs/${abi}/
done

# macOS (ユニバーサルバイナリ)
zig build -Dtarget=aarch64-macos -Doptimize=ReleaseFast
zig build -Dtarget=x86_64-macos -Doptimize=ReleaseFast
lipo -create zig-out/lib/libzylix-arm64.a zig-out/lib/libzylix-x64.a -output ../platforms/macos/libzylix.a

# Linux (x64)
zig build -Dtarget=x86_64-linux-gnu -Doptimize=ReleaseFast
cp zig-out/lib/libzylix.a ../platforms/linux/

# Windows (x64)
zig build -Dtarget=x86_64-windows -Doptimize=ReleaseFast
cp zig-out/lib/zylix.dll ../platforms/windows/

パフォーマンスのヒント

全プラットフォーム共通

  1. 状態変更を最小化: 関連する更新をバッチ処理
  2. リストにキーを使用: 効率的な差分検出を有効化
  3. 遅延読み込み: オンデマンドでデータをロード
  4. メモ化: 高コストな計算をキャッシュ

プラットフォーム固有

プラットフォームヒント
WebWASM ストリーミングコンパイルを有効化
iOSローカル状態には @ObservedObject より @State を優先
Android高コストな計算には remember を使用
macOSカスタム描画よりネイティブコントロールを優先
Linuxインラインスタイルより CSS クラスを使用
Windowsパフォーマンス向けにコンパイル済みバインディングを有効化

デバッグ

全プラットフォーム共通

// Zig でデバッグログを有効化
pub const log_level: std.log.Level = .debug;

// 状態変更をログ
pub fn logStateChange(event: Event) void {
    std.log.debug("イベント: {s}, バージョン: {d}", .{
        @tagName(event),
        state.getVersion()
    });
}

プラットフォーム固有ツール

プラットフォームツール
Webブラウザ DevTools、WASM デバッグ
iOSXcode Instruments、View Debugger
AndroidAndroid Studio Profiler、Layout Inspector
macOSXcode Instruments
LinuxGTK Inspector、Valgrind
WindowsVisual Studio Profiler、WinDbg

次のステップ