dl.so

Ruby/DL は、UNIX の dlopen(3) や Windows の LoadLibrary() などのダイナミックリンカへのインタフェースを提供す る。

Using Ruby/DL

通常は、dl/import.rbの DL::Importable モジュールを使用する。 これはライブラリ関数にアクセスするための高水準の関数を持っている。 あるモジュールを拡張するには以下のように DL::Importable を使用する。

require "dl/import"
module LIBC
  extend DL::Importable
end

以後、このモジュールの dlload と extern メソッドを使用できる。以下のよ うに dlload 使ってライブラリをロードし、それぞれのライブラリ関数に対し て extern を使用することでラッパーメソッドを定義する。

module LIBC
  extend DL::Importable
  dlload "libc.so.6","libm.so.6"
  extern "int strlen(char*)"
end
# Note that we should not include the module LIBC from some reason.

LIBC.strlen を使用することで、ライブラリ関数 strlen() を使用できる。与 えられた関数名の最初の文字が大文字なら、定義されるメソッド名の最初の文 字は小文字になる。

以下のように dl/struct.rb で定義される struct や union 関数を使用す ることで構造体や共用体のメモリイメージを作成することもできる。

require "dl/import"
require "dl/struct"
module LIBC
  extend DL::Importable
  Timeval = struct [       # define timeval structure.
    "long tv_sec",
    "long tv_uses",
  ]
end
val = LIBC::Timeval.malloc # allocate memory.

上の例で、メモリの割り当てに LIBC::Timeval.new ではなく、 LIBC::Timeval.malloc を使用していることに注意。LIBC::Timeval.new は、 作成済みの PtrData オブジェクトをラップするためのものだ。

以下のように モジュール関数 callback を使用したコールバックを定義できる。

module Foo
  extend DL::Importable
  def my_comp(str1,str2)
    str1 <=> str2
  end
  COMPARE = callback "int my_comp(char*,char*)"
end

ここで Foo::COMPARE は、my_comp メソッドを起動する Symbol オブジェクトだ。

DL::Importable モジュールはとても便利だ。しかし、ときにはdlsym() のよ うな低レベル関数を直接使わなければならない場面に出くわす。このような場 合には DL モジュールの関数を使用することになるだろう。これについては次 の節で説明する。

DL module

モジュール DL は数個のモジュール関数と定数を持つ 3 つのクラスから成っ ている。クラス Symbol は呼び出す事ができるシンボルに相当する。クラス PtrData は、C のポインタのようなメモリブロックを示す。クラス Handle か ら具体化されたオブジェクトはオープンしたライブラリの操作を持つ。

Constants

Functions

Handle class

Symbol class

PtrData class

Type specifiers

プロトタイプは以下の型修飾子から成る。プロトタイプの最初の要素は戻り値 の型を意味する。残りの要素は各引数の型を意味する。

C : 文字 (char)
c : 文字を指すポインタ (char *)
H : short 整数  (short)
h : short 整数を指すポインタ (short *)
I : 整数 (char, short, int)
i : 整数を指すポインタ (char *, short *, int *)
L : long 整数 (long)
l : long 整数へのポインタ (long *)
F : 実数 (float)
f : 実数へのポインタ (float *)
D : 実数 (double)
d : 実数へのポインタ(double *)
S : 不変(immutable)の文字列 (const char *)
s : 変更可能(mutable)な文字列 (char *)
A : 配列 (const type[])
a : 変更可能(mutable)な配列 (type[])
P : ポインタ (void *)
p : 変更可能(mutable)なポインタ (void *)
0 : void 関数(これはプロトタイプの最初の文字でなければならない)

cbtype は型修飾子 0, C, I, H, L, F, D, S そして P から成る。例えば:

DL.callback('IPP'){|ptr1,ptr2|
  str1 = ptr1.ptr.to_s
  str2 = ptr2.ptr.to_s
  str1 <=> str2
}