mruby 的 mrbgems 扩展机制完整指南从 Gem 接入、依赖管理到 C/Ruby 混合扩展【免费下载链接】h2oH2O - the optimized HTTP/1, HTTP/2, HTTP/3 server项目地址: https://gitcode.com/gh_mirrors/h2/h2omrbgems 是 mruby 官方提供的库管理器用于以标准化方式将 C 扩展与 Ruby 扩展集成进 mruby 构建。本文以 mrbgems.md 为主体结合本仓库deps/mruby及其 mrbgems 目录中的真实代码系统讲解如何在构建配置中接入第三方 Gem、如何用 GemBox 批量组合扩展、如何编写 C 扩展与 Ruby 扩展、如何管理依赖与冲突以及如何构建可执行的二进制 Gem帮助读者完整掌握 mruby 扩展开发与定制裁剪能力。mrbgems 是什么mrbgems 是 mruby 的库管理器目标是把 C 语言扩展和 Ruby 语言扩展以统一、标准化的方式集成进 mruby。按惯例每个 mrbgem 的名字都以mruby-前缀开头例如提供Time类功能的 Gem 就命名为mruby-time。本仓库的 deps/mruby/mrbgems 目录下就内置了大量核心 Gem如mruby-time、mruby-io、mruby-socket、mruby-compiler以及二进制类 Gemmruby-bin-mruby、mruby-bin-mirb、mruby-bin-mrbc、mruby-bin-strip等同时deps/下还捆绑了 H2O 实际使用的外部 mrbgem如 mruby-digest、mruby-env、mruby-input-stream、mruby-onig-regexp 等。这些 Gem 均遵循统一的mrbgem.rake规范文件组织是理解 mrbgems 机制的最佳范例。在构建配置中启用与添加 mrbgemmrbgems 需要显式激活在构建配置文件中调用conf.gem即可把某个 Gem 加入构建。通过本地路径添加conf.gem /path/to/your/gem/dir也可以使用相对路径conf.gem examples/mrbgems/ruby_extension_example相对路径的解析规则取决于构建配置文件的位置若构建配置文件位于build_config目录则相对路径以MRUBY_ROOT为基准否则相对路径以构建配置文件所在目录为基准。在 H2O 的 mruby 中构建配置统一位于 deps/mruby/build_config 目录其中 default.rb 是被 build_config.rb 推荐的默认配置入口其注释中给出了多种conf.gem用法示例# conf.gem examples/mrbgems/ruby_extension_example # conf.gem examples/mrbgems/c_extension_example do |g| # g.cc.flags -g # append cflags in this gem # end # conf.gem :core mruby-eval # conf.gem :mgem mruby-onig-regexp # conf.gem :github mattn/mruby-onig-regexp # conf.gem :git gitgithub.com:mattn/mruby-onig-regexp.git, :branch master, :options -v可以看到conf.gem既支持路径字符串也支持:core、:mgem、:github、:git等哈希形式的取源方式还支持传入代码块对单个 Gem 的编译参数做局部定制。从 Git 仓库远程取 Gemconf.gem :git https://github.com/masuidrive/mrbgems-example.git, :branch master conf.gem :github masuidrive/mrbgems-example, :branch master conf.gem :bitbucket mruby/mrbgems-example, :branch master注意:bitbucket选项只支持 git 协议当前版本不支持 hg。如果 Gem 位于仓库的子目录可用:path指定子目录conf.gem github: mruby/mruby, path: mrbgems/mruby-socket本仓库的mruby-bin-mirb、mruby-bin-mrbc等 Gem 正是以:core形式被 default.gembox 引入的conf.gem :core mruby-bin-mrbc:core表示从 mruby 自带的mrbgems目录中查找对应名称的 Gem。从 mgem-list 索引取 Gemmgem-list 是 mruby 社区的 Gem 索引仓库通过:mgem选项可以直接引用其中的 Gemconf.gem :mgem mruby-yaml conf.gem :mgem yaml # mruby- 前缀可以省略固定依赖的提交版本需要固定某个 Gem 的检出提交时使用:checksum_hash选项conf.gem mgem: mruby-redis, checksum_hash: 3446d19fc4a3f9697b5ddbf2a904f301c42f2f4e缺失依赖的自动解析如果构建中缺少某个 Gem 的依赖mrbgems 的依赖求解器会从 mruby 核心 Gem:core或 mgem-list 中自动引用对应 mrbgem。同名 Git Gem 冲突与 canonical 选项当多个基于 git 的 Gem 具有相同的基础名即默认检出目录名时除非它们的仓库 URL、分支名和提交 ID即 checksum hash完全一致否则会报错。可以通过先显式导入自己偏好的版本并设置canonical: true来绕过conf.gem github: me/mruby-yaml, branch: my-hacked-branch, canonical: true设置后系统会在多数情况下静默地忽略后续针对同名 Gem 的克隆尝试。需要注意canonical只影响从 git 克隆 Gem 这一环节并不解决版本冲突。如果 Gem 的 rakefile 中声明的版本与某个依赖不兼容构建仍然会失败。GemBox批量组合 mrbgem当需要一次性加入一批 mrbgem或希望按不同配置切换 Gem 组合时可以使用 GemBox。GemBox 是一个文件内部以与config.gem相同的格式列出要加载的 mrbgem但整体包裹在MRuby::GemBox对象中通过config.gembox boxname加载。下面是一个包含mruby-time与mrbgems-example的 GemBox 示例MRuby::GemBox.new do |conf| conf.gem #{root}/mrbgems/mruby-time conf.gem :github masuidrive/mrbgems-example endGemBox 与MRuby::Build使用相同的约定。要让 mruby 识别GemBox 文件必须以.gembox扩展名保存在mrbgems目录中。把上面的内容保存为mrbgems/custom.gembox后在构建配置文件的 build 块中加入conf.gembox custom构建时customGemBox 即被读取mruby-time与mrbgems-example会被加入构建。如果想把 GemBox 放在 mruby 目录之外则必须使用绝对路径conf.gembox #{ENV[HOME]}/mygemboxes/custommruby 自带的两个 GemBoxmruby 内置两个 GemBoxdefault.gembox包含 mruby 的若干核心组件。其实现依次引用了stdlib、stdlib-ext、stdlib-io、math、metaprog五个 gembox并加入mruby-bin-mrbc、mruby-bin-mirb、mruby-bin-mruby、mruby-bin-strip、mruby-bin-config五个可执行 Gemfull-core.gembox包含mrbgems目录下除mruby-bin-debugger、mruby-test之外的所有 Gem。其实现直接扫描目录MRuby::GemBox.new do |conf| Dir.glob(#{root}/mrbgems/mruby-*/mrbgem.rake) do |x| g File.basename File.dirname x conf.gem :core g unless g ~ /^mruby-(?:bin-debugger|test)$/ end end在 deps/mruby/build_config/default.rb 中正是通过conf.gembox default引入整套默认 Gem 集。此外mrbgems目录下还提供了default-no-fpu.gembox、default-no-stdio.gembox、math.gembox、stdlib.gembox等更细粒度的组合方便按平台与需求裁剪。GEM 目录结构一个最完整的 mrbgem 目录结构如下- GEM_NAME - Gem 名称 | - README.md - Gem 说明文档 | - mrbgem.rake - Gem 规格文件Specification | - include/ - Ruby 扩展所需的头文件会被导出 | - mrblib/ - Ruby 扩展源码 | - src/ - C 扩展源码 | - tools/ - 可执行程序源码C | - test/ - 测试代码Rubymrblib目录存放用于扩展 mruby 的纯 Ruby 文件src目录存放用于扩展 mruby 的 C/C 文件include目录存放 C/C 头文件test目录存放供mrbtest使用的 C/C 与纯 Ruby 测试文件mrbgem.rake是编译 C 与 Ruby 文件所需的规格描述README.md是 Gem 的简要说明。以本仓库为例mruby-time 遵循mrblib src mrbgem.rake结构其 C 实现在 src/time.c 中通过 mruby C API 定义Time类mruby-bin-mirb 则展示了tools/目录的二进制 Gem 结构。构建流程与 mrbgem.rake 规格文件mrbgems 要求每个 Gem 目录下必须存在名为mrbgem.rake的规格文件。一个典型的规格文件如下MRuby::Gem::Specification.new(c_and_ruby_extension_example) do |spec| spec.license MIT spec.author mruby developers spec.summary Example mrbgem using C and Ruby end构建过程会根据该规格编译 Object 文件与 Ruby 文件编译结果被加入lib/libmruby.a。这个静态库把 Gem 的功能暴露给mruby、mirb等工具。信息属性MRuby::Gem::Specification内可设置以下信息属性spec.license或spec.licenses该 Gem 采用的一个或多个许可证spec.author或spec.authors开发者名字或列表spec.version当前版本号spec.description详细描述spec.summary一行短描述设置后会在 rake 的构建摘要中打印spec.homepage主页spec.requirements供用户了解的外部需求license与author是每个 Gem 必填的属性仓库中的真实 Gem 均遵循这一规范例如 mruby-time/mrbgem.rakeMRuby::Gem::Specification.new(mruby-time) do |spec| spec.license MIT spec.author mruby developers spec.summary standard Time class end而 mruby-env/mrbgem.rake 展示了authors复数与version的用法MRuby::Gem::Specification.new(mruby-env) do |spec| spec.license MIT spec.authors Internet Initiative Japan Inc. end声明依赖add_dependency当 Gem 依赖其他 Gem 时使用spec.add_dependency(gem, *requirements[, default_get_info])MRuby::Gem::Specification.new(c_and_ruby_extension_example) do |spec| spec.license MIT spec.author mruby developers # 添加依赖 mruby-parser版本必须介于 1.0.0 与 1.5.2 之间 spec.add_dependency(mruby-parser, 1.0.0, 1.5.2) # 使用 GitHub 上任意版本的 mruby-uv spec.add_dependency(mruby-uv, 0.0.0, :github mattn/mruby-uv) # 使用 GitHub 上最新版 mruby-onig-regexp版本要求可省略 spec.add_dependency(mruby-onig-regexp, :github mattn/mruby-onig-regexp) # 仅测试时激活的额外 gem spec.add_test_dependency(mruby-process, :github iij/mruby-process) end版本要求与默认 Gem 信息都是可选的。仓库中的实际例子可见 mruby-bin-mrbc/mrbgem.rakeMRuby::Gem::Specification.new mruby-bin-mrbc do |spec| spec.license MIT spec.author mruby developers spec.summary mruby compiler executable spec.add_dependency mruby-compiler, :core mruby-compiler ... end以及 mruby-onig-regexp/mrbgem.rake 中的add_dependency mruby-string-ext, core: mruby-string-ext。版本运算符版本要求支持以下运算符等于!不等于大于小于大于等于小于等于~大于等于当前版本且小于下一个主版本例 1~ 2.2.2表示 2.2.2且 2.3.0例 2~ 2.2表示 2.2.0且 3.0.0当传入多个版本要求时依赖必须同时满足全部要求。默认 Gem 信息与覆盖可以在add_dependency的最后一个参数传入Hash作为默认 Gem 信息用于在构建配置中未定义该依赖时使用。其格式与MRuby::Build#gem方法的参数相同只是不能作为路径型 Gem 位置使用。当需要某个特定版本的依赖时在构建配置中使用MRuby::Build#gem即可覆盖默认 Gem。声明冲突add_conflict如果存在互相冲突的 Gem使用spec.add_conflict(gem, *requirements)其中requirements参数与add_dependency一致MRuby::Gem::Specification.new some-regexp-binding do |spec| spec.license BSD spec.author John Doe spec.add_conflict mruby-onig-regexp, 0.0.0 spec.add_conflict mruby-hs-regexp spec.add_conflict mruby-pcre-regexp spec.add_conflict mruby-regexp-pcre end复杂构建选项当 Gem 有更复杂的构建需求时可在规格中使用以下选项spec.cc.flagsC 编译器参数spec.cc.definesC 编译器宏定义spec.cc.include_pathsC 编译器头文件搜索路径spec.linker.flags链接器参数spec.linker.libraries链接库spec.linker.library_paths链接器附加库路径spec.bins生成的可执行文件名spec.rbfiles要编译的 Ruby 文件spec.objs要编译的 Object 文件spec.test_rbfiles集成进 mrbtest 的 Ruby 测试文件spec.test_objs集成进 mrbtest 的 Object 测试文件spec.test_preloadmrbtest 的初始化文件此外还可以用spec.mruby.cc与spec.mruby.linker为编译器和链接器添加全局参数。仓库中 mruby-onig-regexp/mrbgem.rake 是复杂构建的典型范例它先探测系统是否已安装onigmo/oniguruma库通过search_package与search_header_path找不到时则通过spec.bundle_onigmo方法自动解包捆绑的onigmo-6.2.0.tar.gz、调用 autotools 构建静态库、把产物对象并入libmruby.a并动态追加cc.defines与cc.include_paths完整展示了cc、linker、bins、add_dependency等规格选项的组合用法。include_paths 与依赖传播Gem 可以把 include 路径导出给依赖它的其他 Gem。默认情况下/...绝对路径.../{GEM_NAME}/include会被导出因此不建议把 Gem 的本地头文件放在include/下。导出具有追溯性例如 B 依赖 C、A 依赖 B 时A 也能获得 C 导出的 include 路径。被导出的 include_paths 会自动追加到 Gem 本地的 include_paths 中如果构建需求更复杂可以使用spec.export_include_paths访问器。C 扩展mruby 可通过 C API 集成 C 库实现扩展。前提条件mrbgems 要求实现名为mrb_YOURGEMNAME_gem_init(mrb_state)的 C 函数其中YOURGEMNAME替换为 Gem 名称。若 Gem 名为c_extension_example初始化函数如下void mrb_c_extension_example_gem_init(mrb_state* mrb) { struct RClass *class_cextension mrb_define_module(mrb, CExtension); mrb_define_class_method(mrb, class_cextension, c_method, mrb_c_method, MRB_ARGS_NONE()); }Finalize 终结函数mrbgems 还要求实现mrb_YOURGEMNAME_gem_final(mrb_state)终结函数用于释放资源void mrb_c_extension_example_gem_final(mrb_state* mrb) { free(someone); }从源码结构看gem_init/gem_final与 mruby 核心的类定义宏如mrb_define_module、mrb_define_class_method配合构成了 C 扩展的标准初始化/清理生命周期。目录结构示例- c_extension_example/ | - README.md (可选) | - src/ | | | - example.c - C 扩展源码 | - test/ | | | - example.rb - C 扩展测试代码 | - mrbgem.rake - Gem 规格文件以仓库中的 mruby-time 为例其 src/time.c 通过 mruby C API 定义了完整的Time类含时间获取、格式化、时区转换等功能并针对不同平台处理gettimeofday、gmtime_r等可移植性问题是研究 C 扩展实现细节的优质样本。Ruby 扩展mruby 也可以用纯 Ruby 扩展支持覆写已有类或新增类。把所有 Ruby 文件放入mrblib目录即可。前提条件无。目录结构示例- ruby_extension_example/ | - README.md (可选) | - mrblib/ | | | - example.rb - Ruby 扩展源码 | - test/ | | | - example.rb - Ruby 扩展测试代码 | - mrbgem.rake - Gem 规格文件C 与 Ruby 混合扩展mruby 可以同时用 C 和 Ruby 扩展Ruby 文件放入mrblibC 文件放入src。关键执行顺序mrblib下的 mruby 代码会在 Gem 的 Cinit函数被调用之后执行。因此必须保证mruby 脚本依赖 C 代码而C 代码不依赖 mruby 脚本。目录结构示例- c_and_ruby_extension_example/ | - README.md (可选) | - mrblib/ | | | - example.rb - Ruby 扩展源码 | - src/ | | | - example.c - C 扩展源码 | - test/ | | | - example.rb - C 与 Ruby 扩展测试代码 | - mrbgem.rake - Gem 规格文件本仓库 H2O 的 mruby 处理程序lib/handler 下的相关 mruby 集成正是依托这类混合扩展机制将 C 层的请求处理能力与 Ruby 层的业务脚本结合起来。二进制 GemBinary Gems部分 Gem 会在bin目录下生成可执行文件这类 Gem 称为二进制 Gem。其命名惯例以mruby-bin为前缀例如mruby-bin-mirb和mruby-bin-strip。在mrbgem.rake中通过spec.bins指定可执行文件名。入口函数main()应位于tools/bin/*.c中bin为可执行文件名。bin目录下的 C 文件会被编译并链接进可执行文件但不会包含进libmruby.a而mrblib与src下的文件则会进入libmruby.a。强烈建议二进制 Gem 不要包含mrblib和src目录以将普通 Gem 与二进制 Gem 明确分离。目录结构示例- mruby-bin-example/ | - README.md (可选) | - bintest/ | | | - example.rb - 二进制 Gem 测试代码 | - mrbgem.rake - Gem 规格文件 | - mrblib/ - Ruby 扩展源码可选 | - src/ - C 扩展源码可选 | - tools/ | - example/ - 可执行文件名称目录 | - example.c - 可执行文件源码含 main仓库中的真实范例是 mruby-bin-mrbc/mrbgem.rake它通过spec.bins声明生成mrbc可执行文件把tools/mrbc/*.c编译链接为build/bin/mrbc并将mrbc加入build.bins同时通过add_dependency mruby-compiler, :core mruby-compiler依赖编译器核心 Gem。类似的还有 mruby-bin-mirb/mrbgem.rake它额外展示了根据宿主环境探测 readline/linenoise 并动态调整cc.defines与linker.libraries的自动化处理。在 H2O 中的实际应用本仓库将 mruby含 mrbgems 机制作为嵌入式脚本引擎集成于 H2O Web 服务器中构建层面mruby 通过 build_config.rb 指向 build_config/default.rb再由conf.gembox default加载 default.gemboxGem 层面H2O 在 deps 目录下捆绑了mruby-digest、mruby-env、mruby-input-stream、mruby-json、mruby-onig-regexp、mruby-require、mruby-class-new-fiber-safe、mruby-dir、mruby-errno、mruby-file-stat等 mrbgem其mrbgem.rake规格如 mruby-env/mrbgem.rake、mruby-input-stream/mrbgem.rake全部遵循本文所述的规范编写使用层面H2O 的 mruby 处理程序lib/handler/mruby相关源码通过这些 Gem 获得文件系统、环境变量、正则表达式、JSON、摘要算法等能力并配合mruby-require实现脚本加载。如果需要自定义 H2O 内嵌 mruby 的扩展集可按本文方法编辑构建配置复制 build_config/default.rb 为自定义配置用conf.gem/conf.gembox增删 Gem再通过rake MRUBY_CONFIG/path/to/myconfig.rb编译即可得到按需裁剪的 mruby 运行时。总结mrbgems 为 mruby 提供了一套完整、标准化的扩展管理体系conf.gem负责把本地或远程git/github/bitbucket/mgem的 Gem 接入构建MRuby::GemBox支持批量组合与按配置切换mrbgem.rake规格文件统一描述 Gem 的信息、依赖、冲突与编译选项gem_init/gem_final规定了 C 扩展的生命周期mrblib/src/include/tools/test目录划分了各类源码与测试的职责。无论是为 mruby 开发一个简单的Time类扩展还是像 H2O 一样把整套脚本运行时嵌入服务器掌握 mrbgems 都是定制与扩展 mruby 的基础。【免费下载链接】h2oH2O - the optimized HTTP/1, HTTP/2, HTTP/3 server项目地址: https://gitcode.com/gh_mirrors/h2/h2o创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
企业数字化 ERP 产品动态
相关推荐
Airbyte source-e2e-test 贡献者指南:Mock JSON 随机记录生成原理与 Cloud 变体约束 数据工程数据集成ETL后端大数据 【免费下载链接】airbyte Open-source data movement for ELT pipelines and AI agents — from APIs, databases & files to warehouses, lakes, and AI applications. Both self-hosted and Cloud. 项目地址: https://gitcode.… · 2026/9/23 17:52:42
锡矿哪里多?搞懂这3个核心考点,高频面试题不再挂 锡矿哪里多?搞懂这3个核心考点,高频面试题不再挂 复制来的代码跑不通,报错信息看都看不懂,调试半天还是原地打转。这种痛苦,相信不少刚入行的工程师都经历过。特别是在准备那些被称为“拦路虎”的高频面试题时,往往因为对底层逻辑的一知半解,导致现场… · 2026/9/23 17:52:29
小米所有手机型号大全:5个高频面试题背后的选型逻辑 小米所有手机型号大全:5个高频面试题背后的选型逻辑 配置环境就卡半天,是不是你面试前的常态?别急,这往往不是电脑的问题,而是你对底层逻辑没吃透。在技术圈摸爬滚打十年,我发现一个扎心的事实: 80%的“环境崩溃”其实是“认知错位” 。… · 2026/9/23 17:52:23
桥坚强避坑指南:3个致命错误让你的实战项目全白费 桥坚强避坑指南:3个致命错误让你的实战项目全白费 配置环境就卡半天?别急,先看看你的桥坚强代码是不是踩了这3个坑。我在做实战项目时,见过太多应届生因为不懂底层逻辑,把好好的架构搞崩了。今天这篇避坑指南,专门拆解桥坚强在真实业务中的高频故障,… · 2026/9/23 18:34:09
PaddleSpeech 错误率计算模块深入解析:WER 与 CER 的实现原理、调用链与测试验证 人工智能语音音频 【免费下载链接】PaddleSpeech Easy-to-use Speech Toolkit including Self-Supervised Learning model, SOTA/Streaming ASR with punctuation, Streaming TTS with text frontend, Speaker Verification System, End-to-End Speech Translation and Keyword… · 2026/9/23 18:34:02
PreSonus Studio Pro 8.0.2专业音频解决方案解析 1. 项目概述:PreSonus Studio Pro 8.0.2全平台专业音频解决方案作为一款横跨Mac/Win双系统的专业音频工作站,PreSonus Studio Pro 8.0.2在音乐制作和直播领域已经建立了稳固的口碑。我使用这个软件完成过商业级专辑混音和超过200场专业直播,其… · 2026/9/23 18:33:55
3步搞懂Flash Cookie原理与源码,面试不再丢分 3步搞懂Flash Cookie原理与源码,面试不再丢分 官方文档翻了三遍还是云里雾里?别急, Flash Cookie 这个看似冷门的概念,实则是前端面试中的 高频面试题 。很多候选人卡在“为什么它叫 Flash”以及“它和… · 2026/9/23 18:33:49
我的开源项目 Easy WebBridge 我做网页自动化时,最容易卡住的地方往往不是点击按钮,而是让脚本接上“那个已经登录好的浏览器”。
新开一个 Chrome 不难,麻烦在后面:重新登录、重新过验证、找回原来的页面。电脑里如果同时开着 Chrome、Edge、QQ 浏览器&#… · 2026/9/23 18:33:49
1327个高频API速查手册:别再死记硬背,实战选型看这篇 1327个高频API速查手册:别再死记硬背,实战选型看这篇 看了一堆教程还是不会写项目?这是无数转行学员的噩梦。你背了满屏的 for 循环和 if 判断,真到了公司接手烂代码,或者面试被问“这个场景用什么库最合适”,脑子瞬间一片空白。… · 2026/9/23 18:33:49
3招搞定手机怎么下载微信面试难题实战项目解析 3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A… · 2026/9/23 0:00:03
你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 面试被问“高并发下如何保证消息不丢失”,你张口就是“用Redis”,结果面试官追问“如果Redis宕机了怎么办”,你瞬间卡壳。这种场景太常见了,很多新手在背八股文时,只记住了技术名词… · 2026/9/23 0:00:29