2019年3月6日水曜日

Ruby で native extension な gem を作成する方法

概要

過去に gem を作成する方法を紹介しました
今回は C++ 言語を使った native extension を作成する方法を紹介します

環境

  • macOS 10.14.3
  • Ruby 2.5.1p57

プロジェクト作成

gem を開発するためのプロジェクトを作成しましょう

  • bundle gem firstext

ext ディレクトリの準備

C 言語で実装するための準備をします
決められたディレクトリとファイルを作成します
ポイントは extconf.rbextconf.c です

  • cd firstext/
  • mkdir -p ext/firstext
  • vim ext/firstext/extconf.rb
require "mkmf"

abort "missing malloc()" unless have_func "malloc"
abort "missing free()"   unless have_func "free"

create_makefile "firstext/firstext"

mallocfree という関数が使えるかチェックします
使えない場合はエラーを返します
今回はどちらのメソッドも使いませんがサンプルなので入れています

  • touch ext/firstext/firstext.c
  • touch lib/firstext.rb

ライブラリ参照 (firstext.rb)

ビルドで作成される成果物を参照しておきます

  • vim lib/firstext.rb
require "firstext/version"
require "firstext/firstext"

extconf.rb で定義した create_makefile と同じパスを指定します

サンプルコード (firstext.c)

実際に C++ 言語でライブラリを作成します
今回は簡単な文字列を表示する関数を定義しています

  • vim ext/first/firstext.c
#include <ruby.h>

void func1(VALUE self, VALUE str) {
  char* s = StringValuePtr(str);
  printf("%s\n", s);
}

void Init_firstext(void) {
  VALUE fe = rb_define_class("FirstExt", rb_cObject);
  rb_define_method(fe, "func1", func1, 1);
}

ビルド

ビルドします
extconf.rb を実行して次に make します

  • cd ext/firstext
  • ruby extconf.rb
checking for malloc()... yes
checking for free()... yes
creating Makefile
  • make

動作確認

Mac の場合 firstext.bundle が作成されます
以下のように実行すると定義した関数をコールすることができます

  • cd ../../
  • ruby -Ilib:ext -r 'firstext' -e 'FirstExt.new.func1("hoge")'

最後に

とりあえず native extension を作ってみました
実際には C で実装するのでメモリの割り当てなどを考慮する必要があります

参考サイト

0 件のコメント:

コメントを投稿