[#46647] RubyでWindowsの常駐サービスプログラムを作る方法 — kouichi_someya@...

はじめまして。

12 messages 2009/12/16
[#46649] Re: RubyでWindowsの常駐サービスプログラムを作る方法 — "U.Nakamura" <usa@...> 2009/12/17

こんにちは、なかむら(う)です。

[ruby-list:46715] Re: 拡張ライブラリで引数の数が違うオーバーロード関数の定義の仕方に関する質問

From: Tadashi Saito <shiba@...2.accsnet.ne.jp>
Date: 2009-12-28 04:41:52 UTC
List: ruby-list #46715
斎藤と申します。拡張ライブラリの一作者です。

On Mon, 28 Dec 2009 12:15:21 +0900
ueda <tueda@wolf.dog.cx> wrote:

> 今C++でRubyの拡張ライブラリを書いています。

自分はC++の知識がないので、オーバーロード以外のところについてしか分かりませんが、
Rubyレベルの引数デフォルト値と、C++のそれとを混同しているのが原因に思えます。

Rubyと拡張ライブラリを媒介するAPIはあくまでCですから、拡張ライブラリもCを意識
しなければなりません。

> // 2つめの引数の指定がない場合はnilのつもり
> VALUE binder_Loader_load (VALUE self, VALUE val_data, VALUE offset=Qnil)

具体的にはこれがよく無いのではないでしょうか。というのも

> void Init_m3g
> {
> rb_define_singleton_method (rb_cLoader, "load",
> (VALUE(*)(...))binder_Loader_load, 2);
> }

と、引数の数として「2」と指定しているのですから、

> ArgumentError: wrong number of arguments (1 for 2)

というエラーが出るのは妥当でしょう。

Rubyで言う
  def load(data, offset = nil)
  ...
というメソッドをCで実装する時は、引数の数に(たいてい)「-1」を指定します。
この場合C側では、rb_scan_args()を使って以下のように実装するのが普通です。

VALUE binder_Loader_load(int argc, VALUE argv[], VALUE self)
{
    VALUE data, offset;
    if (rb_scan_args(argc, argv, "11", &data, &offset) == 1) {
        offset = Qnil;
    }
    :
}

void Init_m3g()
{
    rb_define_singleton_method (rb_cLoader, "load", binder_Loader_load, -1);
    :
}

関数ポインタのキャストも減ってすっきりしますね。
詳しくはREADME.EXT.jaを見てみてください。

--
斎藤ただし

In This Thread