Ruby 2.1.0 リファレンスマニュアル > ライブラリ一覧 > dl/importライブラリ > DL::Functionクラス

class DL::Function

クラスの継承リスト: DL::Function < Fiddle::Function < Object < Kernel < BasicObject

要約

Cの関数ポインタを表すクラスです。

fiddle が利用可能な場合は Fiddle::Function の サブクラスです。そうでない場合は Object のサブクラス です。

DL::CFunc のラッパークラスです。DL::CFuncは プラットフォームによってはうまく動かないため、DL::CFuncを直接使わずに このクラスを通してCの関数を呼び出すべきです。

Cの関数の引数と返り値の型を保持し、DL::Function#call を呼び出した ときには、その型に従い引数を変換してCの関数に渡し、返り値を Rubyのオブジェクトに変換します。

目次

特異メソッド
new
インスタンスメソッド
bind bound? call name to_i unbind

特異メソッド

new(cfunc, argtypes) -> DL::Function[permalink][rdoc]
new(cfunc, argtypes) {|*arg| ... } -> DL::Function

指定された DL::CFunc オブジェクト cfunc をラップする DL::Function オブジェクトを生成して返します。

[PARAM] cfunc:
DL::CFunc オブジェクトを指定します。
[PARAM] argtypes:
cfunc の引数の型をDLに定義された定数の配列で指定します。 unsigned char など unsigned を指定したい場合は - を付けて
    - TYPE_CHAR
を使います。

例:

require 'dl/import'

h = DL::Handle.new
addr = h.sym('strncmp')
cfunc = DL::CFunc.new(addr, DL::TYPE_INT)
func = DL::Function.new(cfunc, [DL::TYPE_VOIDP, DL::TYPE_VOIDP, DL::TYPE_INT])

p func.call("abcd", "abcz", 3)    #=> 0

[SEE_ALSO] DL::TYPE_INT

インスタンスメソッド

bind {|*args| ... }[permalink][rdoc]

自身に指定されたブロックをバインドします。 自身に対して call メソッドが呼ばれたとき、生成時に与えられた DL::CFunc オブジェクトではなく このブロックが呼ばれます。

例:

require 'dl/import'

cfunc = DL::CFunc.new(0, DL::TYPE_INT)
func  = DL::Function.new(cfunc, [DL::TYPE_INT])
func.bind{|i| i + 3  }
p func.call(2)             #=> 5
bound? -> bool[permalink][rdoc]

関数がバインドされているならば真を返します。

# 0 をアドレスとする DL::Function オブジェクトを作ると、それには関数が
# バインドされていないとみなされる
func = DL::Function.new(DL::CFunc.new(0, DL::TYPE_INT), [DL::TYPE_INT])
func.bound? # => false

1.9.x では DL::Function#bind で Ruby の block を bind した場合には このメソッドは正しく動作しません。 2.0以降では修正されています。

[SEE_ALSO] DL::Function#unbind

call(*arg) -> DL::CPtr | Integer | Float | nil[permalink][rdoc]
call(*arg) {|*v| ... } -> DL::CPtr | Integer | Float | nil

自身が表す関数を呼び、返り値を Ruby のオブジェクトに変換して返します。

返り値と引数は DL::Function.new で指定したものが使われます。 より詳しくいうと、

を用います。

引数の変換は以下の通りです。

void* (つまり任意のポインタ型)

nil ならば C の NULL に変換されます DL::CPtr は保持している C ポインタに変換されます。 適当に変換してから、C のポインタに変換します。 文字列であればその先頭ポインタになります。 IO オブジェクトであれば FILE* が渡されます。 整数であればそれがアドレスとみなされます。 どれでもなければ to_ptr を呼び出し DL::CPtr オブジェクトに 変換したのが用いられます。

(unsigned) char/short/int/long/long long

Ruby の整数を C の整数に変換します。

double/float

Ruby の整数 or 浮動小数点数を C の浮動小数点数に変換します

返り値の変換は以下の通りです。

void

nil を返します

(unsigned) char/short/int/long/long long

C の整数を Ruby の整数に変換します

void*(つまり任意のポインタ型)

C のポインタを保持した DL::CPtr を返します。

ブロックを与えた場合、引数の中に DL::Function オブジェクトが もしあれば与えられたブロックをバインドし、その後上と同じように関数を呼びます。 複数の DL::Function オブジェクトを引数に渡した場合は、前にある ほうにバインドされます。

[PARAM] arg:
関数に与える引数を指定します。

例:

require 'dl/import'

h = DL::Handle.new
addr = h.sym('fread')
cfunc = DL::CFunc.new(addr, DL::TYPE_INT)
func = DL::Function.new(cfunc, [DL::TYPE_VOIDP, DL::TYPE_LONG, DL::TYPE_LONG, DL::TYPE_VOIDP])
io = File.open('s.txt')
s = " " * 8
func.call(s, 4, 1, io)
p s                    #=> "hoge    "

例:

require 'dl/import'

h = DL::Handle.new
addr = h.sym('strdup')
cfunc = DL::CFunc.new(addr, DL::TYPE_VOIDP)
func = DL::Function.new(cfunc, [DL::TYPE_VOIDP])
s = 'abc'
ptr = func.call(s)
p ptr.to_s              #=> "abc"
name -> String[permalink][rdoc]

自身が表す関数の名前を文字列で返します。

require 'dl/import'

h = DL::Handle.new
addr = h.sym('strncmp')
cfunc = DL::CFunc.new(addr, DL::TYPE_INT, 'strncmp')
func = DL::Function.new(cfunc, [DL::TYPE_VOIDP, DL::TYPE_VOIDP, DL::TYPE_INT])

p func.name    #=> "strncmp"
to_i -> Integer[permalink][rdoc]

自身が表す関数のアドレスを整数で返します。

require 'dl/import'

h = DL::Handle.new
addr = h.sym('strncmp')
cfunc = DL::CFunc.new(addr, DL::TYPE_INT)
func = DL::Function.new(cfunc, [DL::TYPE_VOIDP, DL::TYPE_VOIDP, DL::TYPE_INT])

p func.to_i    #=>  3084587680
unbind -> ()[permalink][rdoc]

自身から関数をアンバインドします。

1.9.x では DL::Function#bind で Ruby の block を bind した場合には このメソッドは正しく動作しません。 2.0以降では修正されています。