← 都来码← 文档索引VML 是什么原文English

VML 是什么

VML = 一台跑在你手机里的虚拟机,自带一套标准库、一台汇编器、一个字节码格式。

你写的程序(C / Python / BASIC / …共 27 种语言)会被前端编译器编成这台虚拟机认识的指令,再由它跑起来。所以:

为什么不是直接调用系统的编译器

手机上装不了、也跑不动完整的 gcc / CPython。VML 把这些工作放到了编译期—— 编译在前端完成,运行时只需要一台很小的虚拟机。

三级产物

你的源码 (.c)  ──前端编译──▶  .vml(文本汇编)  ──汇编──▶  .vmb(二进制字节码)
                                                                  │
                                                            装载即执行
产物是什么什么时候用
源码你写的平时改这个
.vml文本汇编,能直接看、能 grep想看看编译器把你的代码编成了什么
.vmb二进制字节码要跑就加载它,最快

vml run 三种都认,自动识别。

能画界面、能出声、能震动

VML 程序不是只能打印文字——它有一套完整的手机界面接口:

已经用这套接口写了俄罗斯方块、五子棋、吃豆人、贪吃蛇、飞机大战、钢琴… 都在 examples/ 里,能直接跑。

详见「UI 开发」。

27 种语言,随便挑一门

同一套 VML 接口,27 个前端都能用。你熟悉哪门就用哪门写,编出来的东西跑在同一台虚拟机上。每种语言的详细说明(语法规范 + 这个前端支持什么)在「关于 → 使用说明 → VML 编译器 → 27 种语言」里。

27 种语言,各挑一个例子跑

语言示例跑法
Cexamples/c/app/tetris.c gomoku.c pacman.c mario.c starfall.c **piano.c** **audio_test.c**vml run examples/c/app/gomoku.c
C++examples/cpp/app/snake.cppvml run examples/cpp/app/snake.cpp
C#examples/csharp/app/snake.cs racer.csvml run examples/csharp/app/snake.cs
Objective-Cexamples/objc/app/snake.mvml run examples/objc/app/snake.m
Javaexamples/java/test/catch.javavml run examples/java/test/catch.java
Kotlinexamples/kotlin/test/catch.ktvml run examples/kotlin/test/catch.kt
Swiftexamples/swift/app/plane.swift snake.swiftvml run examples/swift/app/snake.swift
Goexamples/go/app/snake.govml run examples/go/app/snake.go
Rustexamples/rust/app/breakout.rsvml run examples/rust/app/breakout.rs
Dexamples/d/test/catch.dvml run examples/d/test/catch.d
Dartexamples/dart/test/catch.dartvml run examples/dart/test/catch.dart
Pythonexamples/python/app/tetris.pyvml run examples/python/app/tetris.py
JavaScriptexamples/javascript/test/catch.jsvml run examples/javascript/test/catch.js
Luaexamples/lua/app/life.luavml run examples/lua/app/life.lua
Rubyexamples/ruby/test/catch.rbvml run examples/ruby/test/catch.rb
Rexamples/r/test/catch.rvml run examples/r/test/catch.r
Pascalexamples/pascal/test/catch.pasvml run examples/pascal/test/catch.pas
Fortranexamples/fortran/app/sokoban.f90vml run examples/fortran/app/sokoban.f90
BASICexamples/basic/app/whack.bas tetris.basvml run examples/basic/app/whack.bas
Forthexamples/forth/test/parserexp_demo.fsvml run examples/forth/test/parserexp_demo.fs
Schemeexamples/scheme/test/catch.scmvml run examples/scheme/test/catch.scm
Ladderexamples/ladder/test/file_io.ld只能编译,见下

每种语言目录下还有一个 sysinfo.<ext>,它调用 ui_call_json("sysinfo", "") 把设备信息打出来 —— 想知道这门语言能不能用,先跑它。

各语言怎么写

C / C++ / Objective-C —— 最完整的一条路

#include <vml_ui.h>

int main(void) {
    int w = ui_scr_get_w(), h = ui_scr_get_h();
    ui_win_open("演示", w, h);
    ui_2d_clear(0xFF101020);
    ui_2d_text(20, 40, "Hello", 0xFFFFFFFF, 20, 0);
    ui_2d_present();
    while (ui_win_is_closed() == 0) { int m[4]; ui_msg_wait(m, 0); }
    return 0;
}

C# / Java / Kotlin / Dart —— 需要声明一下

这几个前端要求先声明外部函数:

// C#
class P { static void Main() { ui_win_open("演示", ui_scr_get_w(), ui_scr_get_h()); } }
// Java
static native int ui_win_open(String t, int w, int h);
// Dart
external int ui_win_open(String t, int w, int h);

Python / Lua / JavaScript / Ruby / R —— 直接调

ui_win_open("演示", ui_scr_get_w(), ui_scr_get_h())
ui_2d_clear(0xFF101020)
ui_2d_present()

⚠ Python 的列表"写不进去"(b[i] = v 之后读回来还是 0)。棋盘这类可变网格请用共享库提供的整数网格:

ui_grid_clear()
ui_grid_set(3, 1)      # 第 3 格
v = ui_grid_get(3)

BASIC

NATIVE FUNCTION ui_win_open(t AS STRING, w AS INTEGER, h AS INTEGER) AS INTEGER
ui_win_open "打地鼠", w, h

⚠ 形参名不能叫 on(关键字)。

Pascal

{ 注释是 { },不是 // }
program p;
begin
  ui_win_open('演示', ui_scr_get_w(), ui_scr_get_h());
  ui_2d_present();
end.

⚠ 注释里只能写 ASCII —— 中文标点(破折号、逗号)会报「未知字符」。用 // 当注释的话整行会被当成代码。

Forth

S" 演示" ui_scr_get_w ui_scr_get_h ui_win_open

Scheme

(ui_win_open "演示" (ui_scr_get_w) (ui_scr_get_h))

⚠ 用户函数看不见顶层变量(两边的帧指针会撞)。游戏请写成扁平顶层程序,只把"参数全传、不碰全局"的纯函数抽出去。

Fortran

call ui_win_open('演示', ui_scr_get_w(), ui_scr_get_h())

Ladder —— 特殊

它是PLC 梯形图风格的前端,没有"带字符串参数的函数调用"这种语法,所以 UI 那套接口用不了(仓库里的 ladder/file_io.ld 本身就是一个空测试)。它能编译、能跑,但做不了手机界面程序。

共同的坑(与语言无关)

  1. 先问后开:ui_scr_get_w/h → ui_win_open
  2. **每帧 ui_2d_present()**
  3. **重开一局前 ui_msg_clear()**
  4. 定时器要 kill
  5. 数组别越界 —— 报「内存错误」十有八九是它