スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

RubyのC拡張をGemで作る

RubyのC拡張をGemで作る手順のメモ。

1. ひな形作成
sampleという名前でspec付きで作成します。

bundle gem sample -V -t
cd sample

2. Gemfile修正
rake-compilerを追加します。

vi Gemfile
source 'https://rubygems.org'

# Specify your gem's dependencies in sample.gemspec
gemspec
gem "rake-compiler"


3. gemspecの修正
descriptionとsummaryの修正とextensionsを追加します。

vi sample.gemspec
# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'sample/version'

Gem::Specification.new do |spec|
spec.name = "sample"
spec.version = Sample::VERSION
spec.authors = ["aoyagikouhei"]
spec.email = ["aoyagi.kouhei@gmail.com"]
spec.description = %q{Sample description}
spec.summary = %q{Sample summary}
spec.homepage = ""
spec.license = "MIT"
spec.extensions << 'ext/sample/extconf.rb'

spec.files = `git ls-files`.split($/)
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = ["lib"]

spec.add_development_dependency "bundler", "~> 1.3"
spec.add_development_dependency "rake"
spec.add_development_dependency "rspec"
end


4. extconf.rbの作成
生成するライブラリは「n」を追加してsamplenとします。nativeの頭文字を取ってます。
これはsampleにしてしまうと、sample.rbでrequireが出来ないので微妙に名前を変えています。

mkdir -p ext/sample
vi ext/sample/extconf.rb
require "mkmf"
create_makefile("samplen")


5. Rakefileの修正
rake-compilerのデフォルトではC拡張のライブラリをspec.nameで作成してしまうため都合が悪いです。
モンキーパッチを当てて「n」が付くようにします。

vi Rakefile
require "bundler/gem_helper"
gem_helper = Bundler::GemHelper.new(Dir.pwd)
gem_helper.install
gem_spec = gem_helper.gemspec

require 'rake/clean'

require 'rake/testtask'
Rake::TestTask.new

require 'rake/extensiontask'
module Rake
class BaseExtensionTask
def binary(platform = nil)
ext = case platform
when /darwin/
'bundle'
when /mingw|mswin|linux/
'so'
when /java/
'jar'
else
RbConfig::CONFIG['DLEXT']
end
"#{@name}n.#{ext}"
end
end
end

Rake::ExtensionTask.new(gem_spec.name, gem_spec)

require "rspec/core/rake_task"
RSpec::Core::RakeTask.new(:spec)


6. Rubyファイルの修正
C拡張を呼び出します。

vi lib/sample.rb
require "sample/version"
require "samplen"

module Sample
# Your code goes here...
end


7. C拡張の実装
vi ext/sample/sample.c
#include <stdio.h>
#include <ruby.h>

VALUE world(void);

void Init_samplen(){
VALUE mSample;
VALUE cHello;

mSample = rb_define_module("Sample");
cHello = rb_define_class_under(mSample, "Hello", rb_cObject);
rb_define_method(cHello, "world", world, 0);
}

VALUE world(void){
return rb_str_new2("hello world");
}


8. specファイルの修正
vi spec/sample_spec.rb
require 'spec_helper'

describe Sample do
it 'should have a version number' do
expect(Sample::VERSION).not_to be_nil
end

it 'hello world' do
obj = Sample::Hello.new
expect(obj.world).to eq("hello world")
end
end


9. 動作確認
bundle install --path=vendor/bundler
bundle exec rake compile
bundle exec rake spec

10. コミット
vi .gitignore
vendor
lib/samplen.*

git add .
git commit -m "first commit"
スポンサーサイト

COMMENTS

COMMENT FORM

TRACKBACK


この記事にトラックバックする(FC2ブログユーザー)

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。