Ruby 2.1.0 リファレンスマニュアル > ライブラリ一覧 > dlライブラリ
*.dllや*.soなど、ダイナミックリンクライブラリを扱うためのライブラリです。
このライブラリは 2.2.0 で削除されました。2.2.0 以降では fiddle を利用してください。
通常は dl/import ライブラリを require して DL::Importer モジュールを使用します。 DL モジュール自体はプリミティブな機能しか提供していません。 DL::Importer モジュールは以下のようにユーザが定義したモジュールを拡張する形で使います。
require "dl/import" module M extend DL::Importer end
以後、このモジュールで dlload や extern などのメソッドが使用できるようになります。 以下のように dlload を使ってライブラリをロードし、 使用したいライブラリ関数に対して extern メソッドを呼んで ラッパーメソッドを定義します。
require "dl/import" module M extend DL::Importer dlload "libc.so.6","libm.so.6" extern "int strlen(char*)" end # Note that we should not include the module M from some reason. p M.strlen('abc') #=> 3
M.strlen を使用することで、ライブラリ関数 strlen() を使用できます。
構造体も扱うことができます。たとえば gettimeofday(2) を使って現在時刻を得たい場合は以下のとおりです。
require 'dl/import' module M extend DL::Importer dlload "libc.so.6" extern('int gettimeofday(void *, void *)') Timeval = struct( ["long tv_sec", "long tv_usec"]) end timeval = M::Timeval.malloc e = M.gettimeofday(timeval, nil) if e == 0 p timeval.tv_sec #=> 1173519547 end
上の例で、メモリの割り当てに M::Timeval.new ではなく M::Timeval.malloc を使用していることに注意してください。
以下のようにモジュール関数 bind を使用したコールバックを定義できます。
require 'dl/import' module M extend DL::Importer dlload "libc.so.6" QsortCallbackWithoutBlock = bind("void *qsort_callback(void*, void*)", :temp) QsortCallback = bind("void *qsort_callback2(void*,void*)"){|ptr1,ptr2| ptr1[0] <=> ptr2[0]} extern 'void qsort(void *, int, int, void *)' end buff = "3465721" M.qsort(buff, buff.size, 1, M::QsortCallback) p buff #=> "1234567" M.qsort(buff, buff.size, 1, M::QsortCallbackWithoutBlock){|ptr1,ptr2| ptr2[0] <=> ptr1[0]} p buff #=> "7654321"
ここで M::QsortCallback はブロックを呼ぶ DL::Function オブジェクトです。
引数としてポインタを受け取る関数に対しては、ポインタの変わりに 文字列を渡します。文字列はポインタが指すメモリ領域として扱われます。
require 'dl/import' module M extend DL::Importer dlload 'libc.so.6' extern 'void * memmove(void *, void *, unsigned long)' end s = 'xxxyyyzzz' M.memmove(s, 'abc', 3) p s #=> "abcyyyzzz"
char * 以外の型のポインタを受け取る関数に対しても文字列を渡します。
module M extend DL::Importer dlload 'libm.so.6' extern 'double modf(double, double *)' end s = ' ' * 8 p M2.modf(1.25, s) #=> 0.25 p s.unpack('d')[0] #=> 1.0
dl でインポートした C の関数を呼び出すとき、 その引数と返り値はインポートする際に指定した型と Ruby のオブジェクトの種類によって変換されます。
引数の変換は以下の通りです。
nil ならば C の NULL に変換されます DL::CPtr は保持している C ポインタに変換されます。 適当に変換してから、C のポインタに変換します。 文字列であればその先頭ポインタになります。 IO オブジェクトであれば FILE* が渡されます。 整数であればそれがアドレスとみなされます。 どれでもなければ to_ptr を呼び出し DL::CPtr オブジェクトに 変換したのが用いられます。
Ruby の整数を C の整数に変換します。
Ruby の整数 or 浮動小数点数を C の浮動小数点数に変換します
返り値の変換は以下の通りです。
nil を返します
C の整数を Ruby の整数に変換します
C のポインタを保持した DL::CPtr を返します。
fiddle が利用可能な環境では、DL 内部的に fiddle を利用し、 関数呼び出しを実現します。DL 単体では例えば x86_64 のような環境では 正しく動作しませんが、fiddle によってうまく動きます。
DL::CFunc | ダイナミックライブラリの関数を表すクラスです。通常、このクラスを直接使わずに ラッパークラスである DL::Function を使います。 |
DL::CPtr | メモリ領域を表すクラスです。C 言語のポインタに相当します。 |
DL::Handle | オープンされたダイナミックライブラリを表すクラスです。 dlopen(3) が返すハンドラーのラッパーです。 |
DL | UNIX の dlopen(3) や Windows の LoadLibrary() などのダイナミックリンカへの低レベルなインターフェースを提供するモジュールです。 |
DL::DLError | DL のエラー全般を表すクラス。 |
DL::DLTypeError | DL の型変換エラーを表すクラス。 |
dl/import | dl ライブラリのための高レベルインターフェースを提供するライブラリです。 |
dl/types | C の型の別名を定義するライブラリです。 |