Ruby C拡張機能の書き方(ステップバイステップ)
C拡張機能を作成すると、CからRubyを操作できます。
Cの速度で最適化したい特定の重要な方法がある場合、またはCライブラリとRubyの間にインターフェイスを作成したい場合は、これが必要になることがあります。
別の方法は、FFIモジュールを使用することです。
今 :
C拡張機能の書き方を見つけましょう!
最初のC拡張機能
extconf.rb
という名前のファイルを作成します これらの内容で:
require 'mkmf' create_header create_makefile 'foobar'
次に、ruby extconf.rb
を実行します これにより、いくつかのファイルが作成されます(Makefile
&extconf.h
)。これらのファイルは変更しないでください。
次に、foobar.c
を作成します 、この名前はcreate_makefile
に由来します extconf.rb
の行 。必要に応じて変更できますが、.c
と一致する必要があります これが機能するためのファイル名。
foobar.c
の内部 これを追加します:
#include "ruby.h" #include "extconf.h" void Init_foobar() { // Your C code goes here }
これは、C拡張機能の基本的なスケルトンです。 extconf.rb
で宣言した名前を使用する必要があることに注意してください プラス単語Init_
。この場合、Init_foobar
。
これは、make
を実行してコンパイルできます。 、そしてあなたが得るものはso
require
を使用してRubyアプリケーションにロードできるファイル 。
CからのRubyメソッドの記述
Rubyコードから呼び出すことができるc関数を作成できます。これが組み込みのクラスとメソッドの仕組みです。
すべてのRubyメソッドはVALUE
を返す必要があります 。 VALUE
Rubyオブジェクトです。
例 :
VALUE rb_return_nil() { return Qnil; }
次に、この関数をRubyクラスまたはモジュールにアタッチする必要があります。新しいクラスを作成することも、既存のクラスを使用することもできます。
ここでモジュールを作成しています :
void Init_foobar() { VALUE mod = rb_define_module("RubyGuides"); rb_define_method(mod, "return_nil", rb_return_nil, 0); }
rb_define_method
を使用できます このモジュールにC関数をアタッチする方法。
議論は :
mod | |
“ print_hello” | Rubyメソッドの名前 |
rb_print_hello | C関数の名前 |
0 | このメソッドが取る引数の数。変数の引数には-1を使用します |
次に、make
を実行します もう一度拡張機能をコンパイルして、次のように試してください:
require 'foobar' include RubyGuides print_hello
これで、RubyからC関数を呼び出しました!
CからのRubyハッシュの作成
多くの場合、CからRubyオブジェクトを作成および操作する必要があります。
これは、CAPIを使用して行うことができます。
たとえば、ハッシュを作成してそれにいくつかの要素を追加するには:
VALUE create_hash() { hash = rb_hash_new(); rb_hash_aset(hash, rb_str_new2("test"), INT2FIX(1)); return hash; }
ここで注意すべき2つの重要な点は、最初にrb_str_new2
関数、これはRuby文字列を作成します。
次に、INT2FIX
マクロ。これは通常の整数をRuby整数に変換します。
ここで、rb_define_method
を使用してこの関数をRubyに公開すると 1つのキーを持つ通常のRubyハッシュを取得します(test
)&1
の値 。
変更を加えるたびに拡張機能を再コンパイルすることを忘れないでください🙂
文字列の操作
C関数はパラメーターを取ることもできます。
例:
VALUE rb_print_length(VALUE self, VALUE str) { if (RB_TYPE_P(str, T_STRING) == 1) { return rb_sprintf("String length: %ld", RSTRING_LEN(str)); } return Qnil; } void Init_foobar() { rb_define_global_function("print_length", rb_print_length, 1); }
ここでは、VALUE
を使用しています (Rubyオブジェクト)を引数として、RB_TYPE_P
の文字列であることを確認します 大きい。その後、RSTRING_LEN
を使用して文字列の長さを出力します マクロ。
文字列データへのポインタが必要な場合は、RSTRING_PTR
を使用できます。 マクロ。
例 :
VALUE rb_print_data(VALUE self, VALUE str) { if (RB_TYPE_P(str, T_STRING) == 1) { return rb_sprintf("String length: %s", RSTRING_LEN(str)); } return Qnil; }
また、ここに別のパラメーターself
があることに注意してください。 、これはメソッド呼び出しを受け取るオブジェクトです。
Stringクラス自体でこのメソッドを定義する場合は、次のようにします。
void Init_foobar() { rb_define_method(rb_cString, "print_length", rb_print_length, 0); }
概要
RubyプログラムからCのすべての機能にアクセスできるように、RubyのC拡張機能を作成する方法を学びました。また、C関数をRubyに公開する方法と、文字列やハッシュなどのCからのRubyオブジェクトを操作する方法も学びました。
CからRubyと対話するためにさらに多くの関数が必要な場合は、Rubyのソースコードでそれらを見つけてC拡張コードを読む必要があるかもしれません。これは十分に文書化されていないためです。
この記事がお役に立てて面白いと思います。もしそうなら、それをあなたの友人と共有して、彼らもそれを楽しむことができるようにしてください。
-
Rubyでポートスキャナーを作成する方法
なぜポートスキャナーを作成したいのですか? ポートスキャナーを作成することは、トランスポート層であるTCPプロトコルの基本を学ぶための優れた方法です。 ほとんどのインターネットプロトコル(HTTPおよびSSHを含む)で使用されます。 Rubyネットワークプログラミングがどのように機能するかを学ぶのも良い練習です。 ポートについて話すことから始めましょう! ポートとは何ですか? ポートについて話すとき、私たちは本当に何について話しているのですか? O.S.の港(オペレーティングシステム)レベルは、プロセスに関連付けられた単なる「ファイル記述子」です。 ファイル記述子 stdoutのよう
-
Rubyでファイルを読み書きする方法(例付き)
今日は、Rubyでファイルを読み書きして、コンテンツを抽出し、新しいファイルを作成し、必要な情報を見つける方法を学びます。 これから説明します : コンテンツ 1Rubyでファイルを読み取る方法 2Rubyでファイルに書き込む方法 3つのRubyファイルメソッド 4つのディレクトリ操作 5FileUtilsモジュールの使用方法 6まとめ 6.1関連 やってみましょう! Rubyでファイルを読み取る方法 次のようにRubyでファイルを読み取ることができます: ファイルを開く 、open メソッド。 ファイルを読む 、ファイル全体、行ごと、または特定のバイト数。 ファイルを