目录
1.gem布局
2.extconf.rb
3.C扩展
4.rake编译
5.gem说明
6.扩展命名规范
7.扩展阅读
前言:
许多gem使用C库作为扩展,使用ruby的接口来使用C代码。例如nokogiri这个gem包含了两个扩展库libxml2 and libxslt
pg(PostgreSQL的驱动)和mysql,mysql2(mysql的驱动)也使用了c扩展。
创建一个包含扩展的gem包含几个步骤,下面将关注此,是你轻松创建带扩展的gem。这个文档会使用到malloc和free两个c标准库。
一、gem布局
每一个gem都开始于一个包含任务的Rakefile文件,扩展的文件需要放在ext目录下,他是extention的缩写。在这个例子里面,我们会使用my_malloc作为名字。
一些扩展一部分是用C写的,一部分是用ruby写的。如果你要支持多语言扩展,例如C和java。你应该把ext目录下C文件对应的ruby文件也放入到lib目录下。
原文:If you are going to support multiple languages, such as C and Java extensions, you should put the C-specific ruby files under the ext/
directory as well in a lib/
directory.
Rakefile ext/my_malloc/extconf.rb # extension configuration ext/my_malloc/my_malloc.c # extension source lib/my_malloc.rb # generic features
当扩展编译ext/my_malloc/lib/下的
c文件后,就会安装到lib目录下。
二、extconf.rb
extconf.rb中是编译你自己的C扩展所需要的Makefile文件。extconf.rb会检查你的扩展所需要的函数,宏指令(macros)和共享库。如果缺少某一项,extconf.rb会立即退出。
下面这个extconf.rb会检查malloc和free,然后创建一个makefile,再将编译后的lib/my_malloc/my_malloc.so扩展按照。
require "mkmf" abort "missing malloc()" unless have_func "malloc" abort "missing free()" unless have_func "free" create_makefile "my_malloc/my_malloc"
mkmf documentation and README.EXT
查看更多关于创建extconf.rb以及其函数文档的细节。
三、C扩展
C扩展包含malloc和free两个函数到ext/my_malloc/my_malloc.c,如下:
#include <ruby.h> struct my_malloc { size_t size; void *ptr; }; static void my_malloc_free(void *p) { struct my_malloc *ptr = p; if (ptr->size > 0) free(ptr->ptr); } static VALUE my_malloc_alloc(VALUE klass) { VALUE obj; struct my_malloc *ptr; obj = Data_Make_Struct(klass, struct my_malloc, NULL, my_malloc_free, ptr); ptr->size = 0; ptr->ptr = NULL; return obj; } static VALUE my_malloc_init(VALUE self, VALUE size) { struct my_malloc *ptr; size_t requested = NUM2SIZET(size); if (0 == requested) rb_raise(rb_eArgError, "unable to allocate 0 bytes"); Data_Get_Struct(self, struct my_malloc, ptr); ptr->ptr = malloc(requested); if (NULL == ptr->ptr) rb_raise(rb_eNoMemError, "unable to allocate %ld bytes", requested); ptr->size = requested; return self; } static VALUE my_malloc_release(VALUE self) { struct my_malloc *ptr; Data_Get_Struct(self, struct my_malloc, ptr); if (0 == ptr->size) return self; ptr->size = 0; free(ptr->ptr); return self; } void Init_my_malloc(void) { VALUE cMyMalloc; cMyMalloc = rb_const_get(rb_cObject, rb_intern("MyMalloc")); rb_define_alloc_func(cMyMalloc, my_malloc_alloc); rb_define_method(cMyMalloc, "initialize", my_malloc_init, 1); rb_define_method(cMyMalloc, "free", my_malloc_release, 0); }
这个c扩展文件很简单,包含以下几部分。
-
struct my_malloc
to hold the allocated memory -
my_malloc_free()
to free the allocated memory after garbage collection -
my_malloc_alloc()
to create the ruby wrapper object -
my_malloc_init()
to allocate memory from ruby -
my_malloc_release()
to free memory from ruby -
Init_my_malloc()
to register the functions in theMyMalloc
class.
你可以像下面这样测试扩展:
$ cd ext/my_malloc
$ ruby extconf.rb
checking for malloc()... yes
checking for free()... yes
creating Makefile
$ make
compiling my_malloc.c
linking shared-object my_malloc.bundle
$ cd ../..
$ ruby -Ilib:ext -r my_malloc -e "p MyMalloc.new(5).free"
#<MyMalloc:0x007fed838addb0>
但这会跑好一会儿,我们使之自动化。
四、rake编译
rake-compiler 是一个负责编译扩展的任务集合。rake-compiler可以同时使用java或者C在同一个项目里面(nokogiri 就是这么干的),添加rake-compiler灰常简单。
require "rake/extensiontask" Rake::ExtensionTask.new "my_malloc" do |ext| ext.lib_dir = "lib/my_malloc" end现在你就可以使用rake compile编译这个扩展,而且可以hook这个编译任务到其他任务(例如test)
设置lib_dir参数以便放置lib/my_malloc/my_malloc.so(.bundle or .dll)的
扩展文件。
This allows the top-level file for the gem to be a ruby file. This allows you to write the parts that are best suited to ruby in ruby.(待翻译)
例如:
class MyMalloc VERSION = "1.0" end require "my_malloc/my_malloc"设置lib_dir也可以使你包含预编译的扩展,以便适应多个ruby版本。(ruby1.9.3的扩展不适用与ruby2.0.0),
lib/my_malloc.rb会选取合适的扩展来安装。
五、gem说明
构建gem的最后一步就是把extconf.rb注册到gemspec的extensions数组中。
Gem::Specification.new "my_malloc", "1.0" do |s| # [...] s.extensions = %w[ext/my_malloc/extconf.rb] end
现在你可以release这个gem了。
六、扩展命名
为了避免gem中无意识的交互(unintended interactions),最好的做法是每一个gem都放在一个单独的目录下。下面是关于gem命名的建议。
-
ext/<name>
目录包含源代码和extconf.rb
-
ext/<name>/<name>.c
主函数源代码文件 (there may be others) -
ext/<name>/<name>.c
contains a functionInit_<name>
. (The name followingInit_
function must exactly match the name of the extension for it to be loadable by require.) -
ext/<name>/extconf.rb
callscreate_makefile('<name>/<name>')
only when the all the pieces needed to compile the extension are present. - The gemspec sets
extensions = ['ext/<name>/extconf.rb']
and includes any of the necessary extension source files in thefiles
list. -
lib/<name>.rb
containsrequire '<name>/<name>'
which loads the C extension
七、扩展阅读
- my_malloc 包含该扩展的源码以及详细的注释
- README.EXT 详细描述了如何在ruby中构建一个gem
- MakeMakefile 包含 mkmf.rb 的文档, the library extconf.rb uses to detect ruby and C library features
- rake-compiler integrates building C and Java extensions into your Rakefile in a smooth manner.
- Writing C extensions part 1 and part 2) by Aaron Patterson
- Interfaces to C libraries can be written using ruby and fiddle (part of the standard library) or ruby-ffi
相关推荐
gemstash, 一个 RubyGems.org 缓存和 private gem 服务器 什么是 Gemstash?Gemstash是远程服务器( 如 https://rubygems.org ) 和 private gem 源的缓存。在你的控制范围内,如果你使用的是多个可以访问服务器的...
A package (also known as a library) contains a set of functionality that can be invoked by a Ruby program, such as reading and parsing an XML ... See our guide on publishing a Gem at guides.rubygems.org
例如,如果您正在https://rubygems.org/gems/simplecov上查看诸如simplecov之类的gem,它将从Ruby Toolbox中获取信息,它是“一个仍在接受更新的长期项目”。 其他gem将基于Ruby Toolbox收集的指标显示其他信息。
组织RubyGems.org 由几个主要部分组成: Rails 应用程序:管理用户并允许其他人查看 gems 等。 Sinatra 应用程序(Hostess):gem 服务器Gem 处理器:处理传入的 gem 并将它们存储在 S3(生产)或server/ (开发)...
帮助管理和支持 RubyGems.org 的快速命令。 目前帮助通过 SSH 连接到 RubyGems.org 基础设施和运行命令。 安装 $ cd $ git clone git://github.com/rubygems/meg.git .meg 对于 bash 用户: $ echo 'eval "$($...
option.rubygems.org 项目导师的姓名: Nick Quaranto,Benjamin Fleischer 项目团队的名称:丽娜·托雷斯(Lina Torres)的安吉拉(Angela Guette) 项目名称: RubyGems.org采用中心 网址: : 关于该项目: ...
标题“2.4-3.0.rubygems.rar”暗示了这个压缩包可能包含了Ruby Gems从版本2.4到3.0之间的升级或集合,这对于Ruby开发者来说是一个重要的资源,因为版本升级通常会带来性能优化、新功能以及对旧问题的修复。...
RubyGems.org(néeGemcutter) Ruby社区的gem主机。 目的 提供更好的API处理宝石 创建更透明,更易于访问的项目页面 使社区能够改善和增强网站 支持 由管理, 是一个社区资助的组织,通过门票和赞助为和的会议...
- **广泛的资源库:** RubyGems.org是一个庞大的社区驱动的Gems仓库,包含了大量的开源代码供开发者使用。 #### 四、如何使用Ruby Gems 1. **安装Ruby环境:** 首先需要在计算机上安装Ruby运行时环境。 2. **安装...
目前正在进行一些验证工作: 对镜像进行验证(接近完成) 用户根据 rubygems 验证他们的本地 gems(有单独的脚本) Gem 所有者通过 Rubygems.org 进行验证(您将学习如何进行) 作为 gem 所有者,您可以通过...
RubyGems是Ruby编程语言的一个核心组成部分,它提供了一个管理和分发Ruby库和程序的框架。这个名为"rubygems-3.2.27.zip"的压缩包包含了RubyGems的3.2.27版本,这是一个重要的更新,旨在提高稳定性和性能,同时也...
RubyGems(通常简称为Gems)是一个软件包管理系统,允许开发者创建、发布和安装自包含的Ruby模块。这些模块包含了代码、元数据和文档,使得开发人员能够方便地重用和分享代码,类似于Python的pip或Java的Maven库。...
Download from: rubygems.org/pages/download Unpack into a directory and cd there Install with: ruby setup.rb # you may need admin/root privilege For more details and other options, see: ruby setup....
★导航至ruby gem的GitHub或Rubygems.org页面。 在GitHub上打开'Gemfile'或'.gemspec'文件,然后单击任何gem名称。 您将被重定向到gem项目页面。 ★从上下文菜单中打开RubyGems.org中的ruby gem页面。 用鼠标突出...
RubyGems
今天或什至更好的做出贡献,并确保Bundler,RubyGems,Gemstash和其他共享工具在未来数年内都存在。 快速入门指南 设置 Gemstash旨在快速,轻松地进行设置。 到本《快速入门指南》结束时,您将能够将公共资源中的...
从rubygems.org/pages/docs移植内容 从help.rubygems.org知识库移植内容 在这里找到许多StackOverflow / ruby-talk问题并获得其常见答案 填写更多指南! 设置 确保已gem install jekyll ( gem install jekyll ...
1. **安装**:使用`gem install <gem_name>`命令,RubyGems会从官方的Gem仓库(rubygems.org)下载指定gem的最新版本,并将其安装到本地系统。同时,RubyGems还会处理gem的依赖关系,确保所有必需的依赖项都被正确...