LoginSignup
3
1

RubyでC言語を実行してみたった(Ruby拡張ライブラリことはじめ)

Last updated at Posted at 2021-01-29

はじめに

こんにちは。RubyでC拡張ライブラリを作らなければならないことになりそうです。
ここではその最初の一歩を踏み出します。

やってみよう

まずは hello world を作ります。Hello world をC言語で書くと

#include <stdio.h>

int main(void) {
    printf("Hello world\n");
}

みたいな感じになりますね。これをRubyで再現するのを目標にします。

mkmfファイルを書く

Ruby の拡張ライブラリのための Makefile を作成するライブラリだそうです。extconf.rb という名前にするようです。今回は以下のような感じにします。

extconf.rb
require 'mkmf'
create_makefile("hello")

C言語のヘッダーファイルを作成する

ruby.h というファイルをincludeするように設定します。

hello.h
#include "ruby.h"

C言語のソースコードを書く

hello.c
#include "hello.h"
#include <stdio.h>

void Init_hello(void)
{
  printf("Hello world\n");
}

これらは同じディレクトリに配置します。

.
├── extconf.rb
├── hello.c
└── hello.h

作ったる

それでは実行していきます。

ruby extconf.rb

Makefileが作成されたはずです。

.
├── extconf.rb
├── hello.c
├── hello.h
└── Makefile

makeします

make

hello.ohello.so が作成されました。

.
├── extconf.rb
├── hello.c
├── hello.h
├── hello.o
├── hello.so
└── Makefile

できた

この hello.so が作成されたRuby拡張ライブラリということになります。irb から呼び出してみましょう。

irb(main):001:0> irb
irb#1(main):001:0> require './hello.so'
Hello world
=> true

無事にHello worldが出力されました。成功です。
irb -r ./hello.so でも実行できます。

Ruby拡張ライブラリを作るために必要な知識と資料

下記の資料が参考になりそうです。

C言語に触ったことはあるけど、RubyのC拡張はなかなか手が出ない人は次の記事も読んでみてください。

おまけ

せっかく初めての拡張ライブラリ(バイナリファイル)を作成したので、少し中身を観察してみましょう。

lddで共有ライブラリの依存関係をチェックする

ldd hello.so
	linux-vdso.so.1 (0x00007ffc0eb97000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2404384000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f240459e000)

逆アセンブルしてみる

objdump -d -Sl hello.so

今回、逆アセンブルというものを初めてやりましたが、思ったよりも元のコードの情報が残っているのですね。

〜中略〜
0000000000001120 <Init_hello>:
Init_hello():
/home/kojix2/Ruby/tmp/hello/hello.c:5
#include "hello.h"
#include <stdio.h>

void Init_hello(void)
{
    1120:	f3 0f 1e fa          	endbr64 
printf():
/usr/include/x86_64-linux-gnu/bits/stdio2.h:110
}

__fortify_function int
printf (const char *__restrict __fmt, ...)
{
  return __printf_chk (__USE_FORTIFY_LEVEL - 1, __fmt, __va_arg_pack ());
    1124:	48 8d 3d d5 0e 00 00 	lea    0xed5(%rip),%rdi        # 2000 <_fini+0xed0>
    112b:	e9 20 ff ff ff       	jmpq   1050 <puts@plt>

シンボルをチェックする

nm -D hello.so

これは、ffiを使ってバインディグを作る時は、ときどき使いますね。一番最初に Init_helloが見えます。

0000000000001120 T Init_hello
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 w __cxa_finalize@@GLIBC_2.2.5
                 w __gmon_start__
                 U puts@@GLIBC_2.2.5

この記事は以上です。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1