3

C/C++ 構造を Ruby にバインドする方法についてアドバイスが必要です。いくつかのマニュアルを読み、クラス メソッドをクラスにバインドする方法を見つけましたが、構造体フィールドをバインドして Ruby でアクセスできるようにする方法をまだ理解していません。

私が使用しているコードは次のとおりです。

myclass = rb_define_class("Myclass", 0);
...
typedef struct nya
{
    char const* name;
    int age;
} Nya;
Nya* p;
VALUE vnya;
p = (Nya*)(ALLOC(Nya));
p->name = "Masha";
p->age = 24;
vnya = Data_Wrap_Struct(myclass, 0, free, p);
rb_eval_string("def foo( a ) p a end"); // This function should print structure object
rb_funcall(0, rb_intern("foo"), 1, vnya); //  Here I call the function and pass the object into it

Ruby 関数はそれaがポインターであると想定しているようです。ポインターの実際の内容 (つまり ) ではなく、ポインターの数値を出力します["Masha", 24]。明らかに、Ruby 関数はこのオブジェクトを認識できません。オブジェクトのプロパティ名と型を設定していません。

これどうやってするの?残念ながら、私はそれを理解することはできません。

4

3 に答える 3

3

ポインターはすでに Ruby オブジェクトでラップされています。あとは、Ruby ワールドからアクセスする方法を定義するだけです。

/* Feel free to convert this function to a macro */
static Nya * get_nya_from(VALUE value) {
    Nya * pointer = 0;
    Data_Get_Struct(value, Nya, pointer);
    return pointer;
}

VALUE nya_get_name(VALUE self) {
    return rb_str_new_cstr(get_nya_from(self)->name);
}

VALUE nya_set_name(VALUE self, VALUE name) {
    /* StringValueCStr returns a null-terminated string. I'm not sure if
       it will be freed when the name gets swept by the GC, so maybe you
       should create a copy of the string and store that instead. */
    get_nya_from(self)->name = StringValueCStr(name);
    return name;
}

VALUE nya_get_age(VALUE self) {
    return INT2FIX(get_nya_from(self)->age);
}

VALUE nya_set_age(VALUE self, VALUE age) {
    get_nya_from(self)->age = FIX2INT(age);
    return age;
}

void init_Myclass() {
    /* Associate these functions with Ruby methods. */
    rb_define_method(myclass, "name",  nya_get_name, 0);
    rb_define_method(myclass, "name=", nya_set_name, 1);
    rb_define_method(myclass, "age",   nya_get_age,  0);
    rb_define_method(myclass, "age=",  nya_set_age,  1);
}

構造体が保持するデータにアクセスできるようになったので、Ruby で高レベルのメソッドを簡単に定義できます。

class Myclass
  def to_a
    [name, age]
  end

  alias to_ary to_a

  def to_s
    to_a.join ', '
  end

  def inspect
    to_a.inspect
  end
end

参考:README.EXT

于 2012-02-24T15:30:12.853 に答える
1

これは、構造に関するあなたの質問に対する直接的な回答ではありませんが、C++ クラスを Ruby に移植する際の問題に対する一般的な解決策です。

SWIGを使用して、C/C++ クラス、構造体、および関数をラップできます。構造物の場合、卵を焼くために家を燃やすことです。ただし、C++ クラスを Ruby (および他の 20 の言語) に迅速に変換するツールが必要な場合は、SWIG が役立つ可能性があります。

構造を含むあなたのケースでは、(最も単純なケースでは) 行を含む .i ファイルを作成するだけです#include <your C++ library.h>

PS繰り返しますが、これはこの1つの構造体に関する質問に対する直接的な回答ではありませんが、より一般的な解決策を利用できる可能性があります。その場合、これが役立つ場合があります。

于 2012-02-24T11:33:15.510 に答える
0

もう1つのオプションは、RubyInlineを使用することです。C型とRuby型(int、char *、floatなど)の変換のサポートが制限されており、C構造体へのアクセスもサポートされています。APIaccessorのメソッドを参照してください。

于 2012-03-09T14:16:14.330 に答える