☰
mruby 3.3 升级指南:语言特性、C API 与构建系统的用户可见变更全解析
2026/10/12 18:41:45 网站建设 项目流程
  • 编程语言
  • 语言运行时
  • 编译器
  • 解释器
  • 嵌入式

【免费下载链接】mruby

Lightweight Ruby

项目地址:https://gitcode.com/gh_mirrors/mr/mruby
点击查看免费下载

导读

本文是面向 mruby 使用者与嵌入式 Ruby 开发者的完整升级指南,基于仓库内官方变更文档 doc/mruby3.3.md 展开,梳理了从 mruby 3.2 升级到 mruby 3.3 过程中所有用户可见的变更:语言语义调整、配置宏与构建平台、内存 API、C API、mrbgems 生态、构建系统以及大量已修复的缺陷。读完本文,你将掌握 mruby 3.3 的迁移要点、MRB_USE_VM_SWITCH_DISPATCH等配置宏的新旧对应关系、Class#allocate禁用机制、以及各 mrbgem 新增方法(如String#bytesplice、Range#overlap?、Enumerator#size)的底层实现与使用方式,能够把基于 mruby 3.2 的项目平滑迁移到 3.3 并规避所有破坏性变更。

文中标注NOTE的变更属于需要格外留意的破坏性调整;所有结论均以当前仓库的实际源码、配置与测试为依据,文中给出的仓库相对路径可供读者自行核对。

一、版本定位与文档性质

mruby 是一个轻量级 Ruby 实现(项目自述为 "Lightweight Ruby"),其源码与文档均位于本仓库。doc/mruby3.3.md是官方发布的版本变更说明,逐条记录了 mruby 3.3 相对 3.2 的改动,每条改动均关联了对应 commit 或 PR 编号(如 #5902、doc/mruby3.1.md、doc/mruby3.2.md、doc/mruby3.4.md、doc/mruby4.0.md),形成了完整的版本演进脉络,阅读时可以相互参照。

文档按九大板块组织:语言(The language)、配置(Configuration)、mruby 内存 API、C API 变更、mrbgems 变更、构建系统变更、其他破坏性变更、已修复的 Bug、用户可见的 Pull Request 列表。下文沿用该骨架并逐条展开。

二、语言层面(The language)的变更

1.super与方法的alias正确配合

mruby 3.3 修复了方法别名与super的配合问题:当方法经过alias之后,super现在能够正确工作(对应 commit 2ad3f0e)。此前在别名方法中调用super可能产生异常行为,升级后这类代码可以放心使用。

2.callee在别名场景下的行为差异

callee方法在 mruby 中与别名配合时的行为与 CRuby 不同,3.3 对此进行了专门调整(对应 commit f2dc76e)。如果你的代码依赖callee获取原始方法名,需要注意 mruby 的处理方式与 CRuby 存在差异,属于行为差异而非缺陷,设计时需按 mruby 的语义来写。

3. 新增Kernel#respond_to_missing?

mruby 3.3 正式定义了Kernel#respond_to_missing?方法(对应 commit 347586e)。它的作用是配合respond_to?:当对象通过method_missing处理未知方法时,可以让respond_to?的询问也能命中这些"虚拟方法"。

在 src/kernel.c 的实现注释中,mruby 详细描述了其语义:

  • 如果某方法真实存在,respond_to?直接回答true,respond_to_missing?不参与;
  • 如果方法不存在,respond_to?会把询问转交给respond_to_missing?,由它来决定是否应答,行为与 CRuby 一致;
  • 反过来,test/t/kernel.rb 中的大量测试也验证了:一个未实现的方法不能靠respond_to_missing?让respond_to?返回true——只有当方法确实经method_missing处理时才有效。

同时 doc/mruby4.0.md 记载,到 4.0 时respond_to_missing?被进一步定义成私有方法(与 CRuby 一致),升级路线上值得提前了解。测试用例位于 test/t/kernel.rb,覆盖了"已定义方法""未定义方法""undef 之后""未定义 respond_to_missing? 时返回 false"等边界场景。

4. 移除_inspect方法(带递归检查的 inspect)

mruby 3.2 中用于递归检查的_inspect方法在 3.3 被整体移除(涉及 commit e2bbf75、5cb0c74、113565a、0713f2a、6ae6b63、fc9fffc 等一组改动)。这意味着所有依赖_inspect的代码(包括自定义 inspect 逻辑、序列化库等)都必须改造,改用公开的inspect接口。

5. 移除__printstr__方法,改用print

内部打印方法__printstr__在 3.3 中被删除(commit acecee0、192e6e3),任何直接调用__printstr__的代码应替换为标准的print。这属于内部实现细节的清理,对普通业务代码影响有限,但对接底层输出通道的代码需要注意。

6. 新方法String#bytesplice

mruby 3.3 引入了String#bytesplice(commit 5274647、a2e2e83),用于按字节偏移替换字符串片段。与按字符操作的splice不同,字节级操作对二进制数据处理更直观。

其核心实现位于 src/string.c 的str_bytesplice函数,调用形式为:

bytesplice(index, length, str) -> string

该方法在 mrbgems/mruby-io/test/io.rb 中也有实际用例(a.bytesplice(100, 100, "")用于缩短字符串以腾出容量),说明它可用于缓冲区管理类场景。3.3 还专门修复了该方法的若干缺陷(见 issue #5986),使用前建议阅读 src/string.c 的参数约束。

7. 允许return在块中跨越 C 边界

这是 3.3 语言层面最重要的能力扩展之一(PR #6125):此前从 Ruby 块中return到定义块的 C 函数之外会被限制,3.3 起允许return跨越 C 边界返回。这涉及 VM 指令OP_RETURN_BLK的行为扩展——配套的 PR #6126 还修复了"在 C 函数下直接调用OP_RETURN_BLK时的返回值"问题。对于用 C 扩展封装迭代器的 gem 开发者,这一改动直接影响到块的返回语义,升级后相关边界场景的行为更接近 CRuby。

三、配置(Configuration)层面的变更

1. Docker 构建与测试

mruby 3.3 起可以完全用 Docker 完成构建与测试(PR #5961)。仓库根目录提供了开箱即用的配置:

  • Dockerfile:基于ruby:3.2.2-bullseye,预装 python3-pip、shellcheck 等测试依赖,并安装 pre-commit hooks;
  • docker-compose.yml:定义了test服务,执行rake deep_clean && rake -m test:run:serial,并通过环境变量注入MRUBY_CONFIG=ci/gcc-clang、CC=gcc、CXX=g++、LD=gcc等构建参数。

直接运行docker-compose build即可按默认 CI 配置构建镜像,之后可用 docker-compose 启动完整测试。这对 CI 集成和跨环境复现构建非常实用。

2. 新增平台支持:DJGPP(MS-DOS)与 Nintendo Wii

  • DJGPP (MS-DOS):新增i586-pc-msdosdjgpp.rb构建配置(PR #6022),使 mruby 可以运行在 DOS 环境(DJGPP 是面向 DOS 的 32 位 GCC 移植工具链);
  • Nintendo Wii:新增nintendo_wii.rb构建配置(PR #6086)。

新平台配置均位于 build_config 目录下,与已有的chipKITMax32.rb、dreamcast_shelf.rb、gameboyadvance.rb等嵌入式/家用机平台配置并列。

3. 改进的平台:Android 与 Dreamcast

  • Android:修复了 Android 工具链(PR #6013),对应 tasks/toolchains/android.rake;
  • Dreamcast:dreamcast_shelf构建配置被彻底重写(PR #6130),对应 build_config/dreamcast_shelf.rb。

4. 允许为特定 gem 禁用测试

PR #6012 为构建系统引入了"按 gem 关闭测试"的能力,并在关闭时给出警告。这意味着某些在新平台上无法运行的测试可以被显式排除,而不会导致整个测试流程失败,也不会静默跳过(会有警告提示)。

5. 配置宏更名:MRB_NO_DIRECT_THREADING→MRB_USE_VM_SWITCH_DISPATCH

这是一个需要迁移的配置宏变更(PR #5902):

  • 旧宏:MRB_NO_DIRECT_THREADING(以及更早的MRB_DISABLE_DIRECT_THREADING,见 doc/mruby3.0.md 的旧名对照表);
  • 新宏:MRB_USE_VM_SWITCH_DISPATCH——语义从"禁止直接线程化"反转为"显式启用 switch 分发"。

新宏的含义在 doc/guides/mrbconf.md 中有官方说明:

  • 定义该宏后,VM 主循环使用switch 分发;
  • 不定义时,若编译器支持则默认使用computed goto(直接线程化,direct threading)。

即:新宏是"正向开关",直接线程化成为默认路径。在 include/mrbconf.h 中仍保留了向后兼容的映射——只要定义了旧宏(MRB_DISABLE_DIRECT_THREADING或MRB_NO_DIRECT_THREADING),会自动推导出MRB_USE_VM_SWITCH_DISPATCH;而 src/vm.c 中 VM 主循环的实现也围绕该宏展开。升级建议:新项目直接定义MRB_USE_VM_SWITCH_DISPATCH,旧项目尽早从构建配置里移除MRB_NO_DIRECT_THREADING并改用新宏。

四、mruby 内存 API 的变更

1.mrb_default_allocf可由应用覆盖

mruby 3.3 起,应用可以在链接前自行定义mrb_default_allocf来覆盖默认分配函数(commit 34c5d96)。mruby 内部所有内存分配都经由统一入口进行,通过定义同名函数,应用可以只拦截 mruby 自身发起的内存操作,而不影响程序里其他库。

仓库内 doc/guides/memory.md 详细说明了这一机制:内部入口实际名为mrb_basic_alloc_func()(即从前的mrb_default_allocf()),其函数签名为:

void* mrb_default_allocf(mrb_state *mrb, void *ptr, size_t size, void *ud);

应用只要在自己的代码里定义这个符号并在链接时覆盖,就能接管 mruby 的分配、释放与重分配操作,常用于自定义内存池、统计或沙箱约束。

2.mrb_open_allocf将被弃用

与上述改动配套,mrb_open_allocf()进入弃用通道(commit cfee5c2)。doc/guides/memory.md 记载了它的旧用法:

mrb_state *mrb = mrb_open_allocf(my_allocf, ud);

文档明确指出这是 3.3 中的移除项。迁移路径是:不再通过mrb_open_allocf传入自定义分配函数,改为直接覆盖mrb_default_allocf符号后使用标准的mrb_open()。升级前请检查代码中是否仍在使用mrb_open_allocf。

五、C API 的变更

1. 新增错误处理 API 函数

3.3 引入了一批新的错误处理 API 函数(commit 8c8bbd9),用于更规范地构造与抛出异常。与之配套的两项破坏性调整(见下文"其他破坏性变更")共同构成了新的异常处理范式。

2. 新增mrb_vm_ci_env_clear()(MRB_API)

新增函数mrb_vm_ci_env_clear(mrb, ci)以公开 API(MRB_API)形式导出(PR #5945),用于清理调用信息(callinfo)中保存的环境引用,避免REnv对象被意外暴露或长期持有。

include/mruby/proc.h 给出了完整的使用示例:在某些 C 调用点,如果不清除mrb->c->cibase处的环境,后续访问会拿到残留的局部变量环境(示例注释中演示了不清除时[4, 5, 6]的残留泄漏现象)。仓库内 mrbgems/mruby-bin-mirb/tools/mirb/mirb.c 与 mrbgems/mruby-bin-mruby/tools/mruby/mruby.c 都在调用 mruby 执行器后主动调用该函数,可作为标准用法参考。

3. 新函数mrb_check_frozen_value()

新增mrb_check_frozen_value(mrb, v)(commit ccdf75c),用于检查值是否被冻结,若冻结则抛出FrozenError。声明位于 include/mruby.h,适合在 C 扩展里修改对象前做防御性检查。

4.mrb_bug()不再支持格式化

NOTE:mrb_bug()的行为有破坏性变化(commit 82a48bd)——它不再执行格式化。当前签名在 include/mruby.h 中为:

MRB_API mrb_noreturn void mrb_bug(mrb_state *mrb, const char *mesg);

实现位于 src/error.c。升级要求:

  • 如果你在用mrb_bug(mrb, "format %d", n)这类格式化调用,必须改为传入简单字符串(mrb_bug(mrb, "simple message"));
  • 或者改用mrb_raise()系列函数完成带参数的异常构造。

这是最容易在编译期通过的"隐性问题"——代码能编译但运行时行为不同,务必主动排查。

5. 编译器上下文不再使用mrbc_前缀

mruby 3.3 停止使用mrbc_前缀来命名编译器上下文相关 API(commit c5e3cbe)。文档说明:旧名称仍然提供(兼容),但推荐替换为新名称。涉及面包括编译器上下文的创建、解析、生成等函数族。迁移时对照新命名逐个替换即可,无需立即处理但建议清理。

6. 允许禁止Class#allocate

这是 3.3 一个重要的安全/设计能力(PR #5979、#6122、#6123):可以禁止某个类被allocate。提供的宏定义在 include/mruby/class.h:

#define MRB_UNDEF_ALLOCATOR(c) (mrb_assert((c)->tt == MRB_TT_CLASS), (c)->flags |= MRB_FL_UNDEF_ALLOCATE) #define MRB_UNDEF_ALLOCATOR_P(c) ((c)->flags & MRB_FL_UNDEF_ALLOCATE) #define MRB_DEFINE_ALLOCATOR(c) ((c)->flags &= ~MRB_FL_UNDEF_ALLOCATE)
  • 对某个类调用MRB_UNDEF_ALLOCATOR(c)即可禁止allocate;
  • 子类会继承MRB_FL_UNDEF_ALLOCATE标志(PR #6123 的实现),即禁止状态自动沿继承链传递;
  • 想显式放行子类,调用MRB_DEFINE_ALLOCATOR(c);
  • VM 层在 src/class.c 中通过MRB_UNDEF_ALLOCATOR_P(c)检查标志并拒绝分配。

这一机制在 mruby 自带 gem 中被大量使用,例如mruby-binding(mrbgems/mruby-binding/src/binding.c)、mruby-method(mrbgems/mruby-method/src/method.c)、mruby-rational、mruby-complex等都不允许外部allocate内部类型;而mruby-data(mrbgems/mruby-data/src/data.c)与mruby-struct(mrbgems/mruby-struct/src/struct.c)则会在合适时机调用MRB_DEFINE_ALLOCATOR放行。自定义 C 扩展作者可参照这些模式决定自己的类是否允许allocate。

六、mrbgems 的变更

1.default.gembox加入调试器 mrdb

PR #5966 把mruby-bin-debugger(mrdb)加入默认构建集合。当前 mrbgems/default.gembox 中可以看到:

# Generate mrdb command conf.gem :core => "mruby-bin-debugger"

这意味着默认构建现在会产出 mrdb 调试器可执行文件,配合 doc/guides/debugger.md 使用即可对 irep 字节码进行断点调试。

2.mruby-bin-config新选项

mruby-config工具新增了编译信息查询选项(PR #6054),实现位于 mrbgems/mruby-bin-config/mruby-config:

选项输出内容
--cxxC++ 编译器名称
--cxxflags传给 C++ 编译器的标志
--as汇编器名称
--asflags传给汇编器的标志
--objcObjective-C 编译器名称
--objcflags传给 Objective-C 编译器的标志

Windows 批处理版本 mrbgems/mruby-bin-config/mruby-config.bat 同步支持。这些选项便于 C/C++ 混合项目的 Makefile/构建脚本获取准确的编译参数。

3.mruby-binding改名,并与mruby-eval合并

NOTE:mruby 3.2 中的mruby-binding-core在 3.3 更名为mruby-binding(commit 11af5db),同时mruby-eval合并了旧版mruby-binding(PR #5989)。迁移规则非常明确:

  • 使用mruby-binding-core(3.2)→ 替换为mruby-binding;
  • 使用mruby-binding(3.2)→ 替换为mruby-eval。

mruby-binding的配套变化还包括:实现Binding#initialize_copy(PR #5517,同时修复了复制 Binding 对象后局部变量未隔离的问题);Kernel#binding只响应来自 Ruby 的调用(PR #5981),从 C 侧调用不再返回 binding。

4. 各 gem 的新方法与行为变更

按 gem 逐一列举 3.3 的增量:

  • mruby-compar-ext:Comparable#clamp现在接受nil作为参数(commit 836bebc)。实现位于 mrbgems/mruby-compar-ext/mrblib/compar.rb:当传入 Range 且端点(begin/end)为nil时视为"无限小/无限大",例如-20.clamp(0..)得到0、523.clamp(..100)得到100;同时排他区间(0...100)作为参数时抛出ArgumentError。这与 CRuby 的无端点 Range 语义对齐。
  • mruby-compiler:为标识符 token 增加打印名称(commit d7b2e3a),利于编译器诊断信息可读性。
  • mruby-data:允许构造空的Data对象(commit 927a9df)。
  • mruby-enumerator:移除内部属性方法obj、args、kwd、meth、fib(commit 735fa24)——这些原本是内部实现细节,直接依赖它们的外部代码需要改写;同时新增Enumerator#size(commit 861f8bd),实现见 mrbgems/mruby-enumerator/mrblib/enumerator.rb:优先返回构造时传入的 size,否则延迟委托给@obj.size,无法惰性计算时返回nil(如loop.size #=> nil、(1..100).each.size #=> 100)。
  • mruby-fiber:
    • 新增公开 APImrb_fiber_new(mrb, proc)(PR #6097),声明于 include/mruby.h,实现于 mrbgems/mruby-fiber/src/fiber.c,C 扩展可以直接基于 RProc 创建 Fiber;
    • 允许从 C 侧调用Fiber#resume(PR #6106),显著放宽了 C/Ruby 边界上的协程限制;
    • Fiber#to_s的格式改变(PR #6105)。
    • 相关修复:PR #6136 修复了mrb_fiber_resume()与Fiber#transfer组合使用的问题;issue #6060 中提到的 Fiber 相关 SEGFAULT 也已处理。
  • mruby-io:
    • 新增File#atime与File#ctime(commit 321cfe9),实现于 mrbgems/mruby-io/src/file.c,直接返回struct stat的访问时间与状态变更时间;
    • IO.open新增"x" 模式(PR #6081):以排他方式创建文件(文件已存在则失败),对应底层O_EXCL语义;
    • File.new不再接受块(commit 53de964),传入块会被忽略或报错。
  • mruby-method:Method#to_s的格式改变(commit f5bc82f、02f189c)。
  • mruby-numeric-ext:int.pow(n, m)的指数n现在可以是 bigint(commit d482eab),大指数模幂运算可用。
  • mruby-pack:新增指令j、J、b、B、#(commit 2a1e3a5、e7021f1、e17f325):
    • j/J:intptr_t/uintptr_t大小的整数(实现见 mrbgems/mruby-pack/src/pack.c,按平台sizeof(intptr_t)映射为l/q或L/Q);
    • b/B:位串(bit string)指令(mrbgems/mruby-pack/src/pack.c,B为高位在前、b为低位在前);
    • #:注释指令,跳过到行尾(mrbgems/mruby-pack/src/pack.c),可在模板字符串里写注释。
  • mruby-range-ext:新增Range#overlap?(commit 384d0e2),判断两个 Range 是否有公共元素,实现见 mrbgems/mruby-range-ext/mrblib/range.rb:
(1..5).overlap?(4..6) #=> true (1..5).overlap?(7..9) #=> false

实现会先校验参数类型(非 Range 抛出TypeError),并正确考虑exclude_end?与空区间(__empty_range?)的情况。

  • mruby-string-ext:新增String#valid_encoding?(commit eabe2d9),判断字符串在当前编码下是否合法,用法与测试见 mrbgems/mruby-encoding/README.md 和 mrbgems/mruby-encoding/test/string.rb(如"\xfe".force_encoding(Encoding::UTF_8).valid_encoding? #=> false,而 ASCII-8BIT 字符串通常视为合法)。
  • mruby-struct:允许在不指定名称的情况下构造空 Struct(commit c212ede),如Struct.new(:a)一类用法更宽松。
  • mruby-time:三项能力增强:
    • 允许1900 年之前的年份(commit e5de08b);
    • 必要时支持bigint 转换到time_t(commit 7096d27);
    • 正确处理负的time_t(commit b064d7e)。 对历史时间、嵌入式系统的跨纪元场景非常关键。

七、构建系统(build system)的变更

1.rake install任务扩展,bin 目录改为符号链接

NOTE:rake install被扩展(PR #5928),随之而来的影响是:默认情况下mruby/bin/目录下的可执行文件现在是指向构建产物的符号链接(Windows 上为批处理文件)。

如果此前你的脚本/CI 直接引用mruby/bin/mruby这类路径并依赖它们是"实体文件",升级后应改为直接引用构建目录下的实体,例如mruby/build/host/bin/。这改变了安装产物布局,打包分发时需同步调整。

2. presym 转义字符的编码与解码

PR #6011(以及补充的 PR #6045)为 presym 扫描加入了转义字符的编码/解码处理,修复了生成的presym/table.h含非法字符的问题(issue #6044)。这属于构建期生成的符号表处理,对"符号预定义(presym)"机制的用户是透明修复。

3.deep_clean清理默认构建目录

Rakefile 的deep_clean任务现在会移除默认构建目标目录(PR #6032、commit 1e38569),配合rake deep_clean可以彻底清理build/与bin/目录。

八、其他破坏性变更(breaking changes)

除上述各节标注的破坏性项外,还有一批需要留意:

  • mrb_f_raise()变为内部函数(PR #5923、#6070):从MRB_API中降级,声明移入 include/mruby/internal.h,C 扩展不应再直接调用;它目前仅作为Kernel#raise等方法的内部入口使用(见 src/kernel.c)。
  • mrb_make_exception()变为内部函数且参数不同(commit 431f83e、78137f3):现声明于 include/mruby/internal.h,实现于 src/error.c,C 扩展如需构造异常请使用 3.3 新增的公开错误处理 API。
  • File#path不再对参数做#to_path隐式转换(commit d86c4a7):传对象时必须显式转为字符串。
  • 测试框架停止为每个测试文件做独立的 mrb 隔离(commit a20fbe5):共享mrb_state后,测试之间可能互相影响,编写测试时需注意状态清理。
  • RBreak 记住 CI(callinfo)位置(PR #6103):break展开时能回到正确的调用信息位置,修复了 VM 崩溃类问题(issue #6108),语义更精确。

九、已修复的问题(Bugs Fixed)

3.3 修复了大量缺陷,按领域归类如下(对应 issue/PR 编号均可在 doc/mruby3.3.md 中查证):

1. 核心 VM 与语言语义

  • #5725:mrblib 代码中的const_missing异常行为怪异;
  • #5932:C API 用mrb_yield创建块导致崩溃("How to create a block using the C API?");
  • #5944:带 hash 变量调用方法的行为;
  • #5946:常量搜索路径不再从模块切换到 Object;
  • #5949:块与省略括号时 caller 报错行号错误;
  • #5995:块参数中多出一个看似多余的参数;
  • #6060:ngx_mruby 中 Fiber 相关的 SEGFAULT;
  • #6065/#6052:Proc 类处理的空指针解引用;
  • #6068:mrb_vm_exec栈溢出;
  • #6076:块展开可能指向无效 PC;
  • #6108:break导致 VM 崩溃;
  • #6126:C 函数下直接调用OP_RETURN_BLK的返回值错误;
  • #6136:mrb_fiber_resume()与Fiber#transfer组合的修复;
  • #6089:binding.eval处理def表达式与 CRuby 不一致;
  • #6098:无法调用被包装方法的 superclass;
  • #6099:proc 内 return 退出时ensure段不执行。

2. 数值计算

  • #5724:Rational#**缺失;
  • commit 0906cd7:大数舍入函数问题;
  • #5975:64 位整数极值上的相等比较失败;
  • #5985:get_int_operand()中OP_LOADI32的符号扩展;
  • #5987:~(-1 << 64)结果错误。

3. 字符串 / IO / 网络

  • #5986:String#bytesplice缺陷;
  • #5991:mruby 3.2.0 中gets不工作;
  • #5994:mruby-io/src/io.c拼写错误;
  • #5943:TCPSocket#write失败;
  • #6061:String#codepoints性能问题;
  • #6051:mrb_addrinfo_unix_path空指针解引用;
  • #6118:IO#read带 buf 时的问题;
  • #6120:check_file_descriptor()失败时设置 EBADF;
  • #6134:String#unpack1返回数组而非单个字符串;
  • #6067:mrb_string_value_cstr空指针解引用。

4. 内存 / GC / 构建

  • #5789:栈错误导致 backtrace 信息内存不释放;
  • commit b47c8b7:分代 GC 的clear_all_old缺陷;
  • #6041:GC 性能下降;
  • #6029:mrbgems 目录下构建失败;
  • commit a264965:mruby-os-memsize的 irep 尺寸计算;
  • #6044:生成的presym/table.h含非法字符;
  • #6064:MRUBY_PACKAGE_DIR并非总有值;
  • #6055:VisualC++ 下 libmruby 命名问题;
  • #6084:Linux 构建中的错误符号 sink;
  • #6087:构建时 "Remote branch HEAD not found in upstream origin";
  • #6066:Struct.new()相关的空指针解引用;
  • #5974:Windows 下gem_init.c中非法转义序列。

十、升级检查清单

把上文所有NOTE项汇总为可直接执行的迁移清单:

  1. 全局搜索并替换:MRB_NO_DIRECT_THREADING→MRB_USE_VM_SWITCH_DISPATCH(include/mrbconf.h 仍兼容旧宏,但新代码应使用新宏);
  2. 检查mrb_bug()调用:改为传简单字符串,或改用mrb_raise()系列;
  3. 检查 C 扩展中对mrb_f_raise()、mrb_make_exception()、mrb_open_allocf()的使用:这三个 API 已降级/弃用,分别改为公开错误处理 API、覆盖mrb_default_allocf与mrb_open();
  4. 检查_inspect、__printstr__的调用:分别替换为inspect与print;
  5. 检查对Class#allocate的依赖:确认自定义类是否需要MRB_DEFINE_ALLOCATOR()显式放行(子类默认继承禁止标志,见 include/mruby/class.h);
  6. mrbgem 改名:mruby-binding-core→mruby-binding→(必要时)mruby-eval;同时Kernel#binding仅响应 Ruby 调用;
  7. 构建产物路径:rake install后mruby/bin/下为符号链接,分发时改用mruby/build/host/bin/下的实体;
  8. File.new不再接受块、File#path不再做#to_path隐式转换、mruby-enumerator内部属性方法已移除——逐项排查相应调用;
  9. 利用新能力:String#bytesplice、Range#overlap?、Enumerator#size、String#valid_encoding?、IO.open的"x"模式、mruby-pack的j/J/b/B/#指令、Fiber#resume从 C 调用等新特性可放心采用。

结语

mruby 3.3 是一次以"收敛内部实现、对齐 CRuby 语义、扩展嵌入式平台"为主线的版本:语言层面对齐了super/别名、respond_to_missing?、块return跨 C 边界等语义;C API 层引入了更安全的错误处理范式、冻结值检查与 allocate 禁令;构建层面新增了 Docker 支持、DJGPP 与 Wii 平台,并重构了 presym 与安装任务。对于从 3.2 升级的开发者,重点是把上文九项检查清单逐条过一遍;对于新项目,直接采用 3.3 的 API 与配置即可。所有细节均可回到 doc/mruby3.3.md 及文中给出的源码路径进一步核验。

  • 编程语言
  • 语言运行时
  • 编译器
  • 解释器
  • 嵌入式

【免费下载链接】mruby

Lightweight Ruby

项目地址:https://gitcode.com/gh_mirrors/mr/mruby
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询