起因
想验证一门中文编程语言能不能真的"造出游戏",于是用玄铁语言(XuanTie-Lang)配合官方渲染库「渲染」写了一个康威生命游戏。
语言本体是上游刚合并了 macOS/arm64 自举支持的新版本,渲染库基于 raylib。在 Windows 上一切顺利,但换到 macOS 上一路踩坑,前后四个问题,全部修通后生命游戏窗口在 Mac 上跑了起来。
这篇文章记录踩坑过程。它同时也是个信号:中文编程语言 + 图形渲染库,已经可以端到端做出带窗口、带交互的原生程序了。
环境
- 系统:macOS(Apple Silicon / arm64)
- 语言:玄铁语言(XuanTie-Lang),中文编程语言
- 渲染库:「渲染」,基于 raylib + nanosvg
- 工具链:xtl(玄铁语言工具链)
- 编译:tie 后端,玄铁源码 → LLVM IR → clang 链接原生二进制
踩坑一:函数名撞车
第一个报错是编译期重定义:
text
生命游戏.ll:3372:12: error: redefinition of function '@暂停'
排查发现,渲染库公开了一个 公 函 暂停(秒数)(渲染循环暂停),而我的生命游戏源码里正好有个全局变量 设 暂停 = 假(游戏暂停开关)。两个 暂停 同名,LLVM 后端生成两个 @暂停 定义。
解法:源码变量改名 暂停中,避开库函数名。这也算玄铁语言命名空间的一个教训------全局变量和库公开函数共享命名空间,取名要先看看库有哪些公开名。
踩坑二:渲染桥是 Windows 专用代码
改名之后语法、LLVM IR 全部通过,但链接阶段炸了。渲染库有个 C 桥接文件 渲染桥.c(约 1600 行),里面有一段无条件编译的 Windows 声明:
c
typedef unsigned short wchar_t;
extern __declspec(dllimport) int WINAPI MultiByteToWideChar(...);
extern __declspec(dllimport) int WINAPI SetWindowTextW(...);
macOS 上 clang 直接报错:
text
error: typedef redefinition with different types ('unsigned short' vs '__darwin_wchar_t')
error: '__declspec' attributes are not enabled
也就是说渲染桥的 Win32 部分没有做平台隔离,任何非 Windows 平台一编译就死。这类问题不是第一次见------语言本体之前也有 FFI「外」模块和运行时 C 文件用 Windows 专有 API 不隔离的毛病,是同类技术债。
解法:把 Windows 声明区包进 #ifdef _WIN32,非 Windows 平台走 raylib 原生 API。
踩坑三:窗口控制函数也要分平台
XT_SetWindowTitle、XT_SetWindowResizable、XT_SetWindowUndecorated 这三个函数体里无条件调用 Win32 API(MultiByteToWideChar、GetWindowLongPtrW 等)。Windows 上通过 Win32 宽字符 API 设置 Unicode 窗口标题、改写窗口样式;非 Windows 平台直接用 raylib 的 SetWindowTitle、SetWindowState(FLAG_WINDOW_RESIZABLE)、SetWindowState(FLAG_WINDOW_UNDECORATED) 即可,功能等价。
还有两个静态变量(xt_maxsave、xt_maxed)和 XT_POINT 结构、GetCursorPos/GetAsyncKeyState 声明也散落在守卫外,一并包进 #ifdef _WIN32。
踩坑四:GDI 字体没有 mac 实现
渲染桥提供"加载系统字体"能力,底层是 Windows GDI 字体光栅化(XT_FontGDI_Create 一整套:Create/DrawText/Measure/Unload)。这套实现整个包在 #ifdef _WIN32 里,macOS 上链接时报未定义符号:
text
Undefined symbols for architecture arm64:
"_XT_FontGDI_Create"
因为渲染库整体编译进程序,加载系统字体 函数即使没被调用,符号也得存在。
解法:非 Windows 补一个 stub,返回 0 表示"不支持"------调用方拿到 0 后绘制路径回退 raylib 默认字体,不崩溃。macOS 上 raylib 的 LoadFontEx 加载字体文件即可,只是"按系统字体名加载"这套 GDI 专属能力暂缺。
修通之后
四关全过,产出 1.7 MB 的 macOS arm64 原生可执行文件。运行后弹出 800×600 窗口,随机 25% 细胞初始填充,空格暂停/继续、R 重置、鼠标左键画细胞,每 2 帧演化一代------康威规则(活细胞 2-3 邻居存活、死细胞 3 邻居复活)正常运转。
结语
这次踩坑有两点值得说:
- 渲染桥的 Windows 专有代码是上游的平台隔离缺口,和语言本体之前的问题同源。修复补丁已经整理好,计划提交回上游------跨平台适配这种事,Mac 用户随手一测就能给项目贡献一堆价值。
- 玄铁语言 + 渲染库这条链路已经能端到端产出原生 GUI 程序:中文编程写逻辑,raylib 负责图形,tie 后端编成真正的二进制。中文编程语言从"玩具"到"能造游戏",又近了一步。