4

cからrubyコードを呼び出すアプリを書いています。私は少し苦労していて、誰かが私を儀式の方向に向けることができるかどうか疑問に思いました。

私は現在私のCにいます。

#include ruby.h

main()
{
  ruby_init();
  rb_require("myRubyFile");
  rb_funcall(rb_module_new(), rb_intern("RubyFunction"), 0, NULL);
}

私のrubyファイルは私のcファイルと同じディレクトリにあり、myRubyFile.rbと呼ばれ、関数RubyFunction()の定義が含まれています。

これは私が実際にやりたいことの縮小であり、他の人にとって読みやすくするだけです。これが私のcファイルからrubyコードを呼び出す正しい方法であるかどうかについてのフィードバックが必要です。

よろしく

4

3 に答える 3

6

短い答え:

extern VALUE rb_vm_top_self(void); /* Assumes 1.9.  Under 1.8, use the global
                                    * VALUE ruby_top_self
                                    */
...
rb_funcall(rb_vm_top_self(),           /* irb> RubyFunction()                   */
           rb_intern("RubyFunction"),  /* irb> self.RubyFunction() # same thing */
           0,
           NULL);

長い答え:

の最初の引数rb_funcallは、メソッド呼び出しの受信者です。

明示的なクラスまたはモジュールコンテキストの外部にあると仮定すると、すべてのdefrubyvmの「トップレベル」にある暗黙のメインオブジェクトの固有クラスに追加されます。RubyFunction()

ルビーでは、このオブジェクトはトップレベルとしてアクセスできますself

$ cat myRubyFile.rb
# file: myRubyFile.rb
def foo
  puts "foo"
end

$ irb
irb> require "myRubyFile"
=> true
irb> foo
foo
=> nil
irb> self.foo()    # same thing, more explicit
foo
=> nil
irb> self
=> main

1.9未満のCでは、上記のようにアクセスできます。

于 2010-05-11T15:29:58.283 に答える
0

私は次のアプローチを使おうとしています。

データを共有するための基本的な構造

typedef struct ruby_shared_data {
    VALUE obj;
    ID method_id;
    int nargs;
    VALUE args[4];
} ruby_shared_data;

コードの一部でrubyオブジェクトを呼び出すための関数を作成します

static VALUE ruby_callback(VALUE ptr) {

    ruby_shared_data *data = (ruby_shared_data*)ptr;

    return rb_funcall2(data->obj,data->method_id,data->nargs,data->args);
}

コードの一部で...

    ruby_shared_data rbdata;

    rbdata.obj = obj;
    rbdata.method_id = rb_intern("mycallback");
    rbdata.nargs = 1;
    rbdata.args[0] = rb_str_new2("im a parameter");

    int error = 0;
    VALUE result = rb_protect(ruby_callback,(VALUE)&rbdata,&error);

    if (error)
            throw "Ruby exception on callback";

rb_funcallをrb_protectでラップすることは常に良い考えです。

もう1つの興味深いことは、コールバックのパラメーターを知ることです。1つのアプローチは次のとおりです。

ruby_shared_data rbdata;

rbdata.obj = callback;
rbdata.method_id = rb_intern("arity"); 
rbdata.nargs = 0;

int error = 0;
VALUE result = rb_protect(ruby_callback,(VALUE)&rbdata,&error);

if (error)
        throw "Ruby exception on callback";

narguments = NUM2INT(result);
于 2015-08-10T20:43:12.923 に答える
-2

ルビーで再構築したくない複雑なCプロジェクトがない限り、C内からルビーを呼び出すのは好きではありません。

Cとルビーの間で相互作用する2つの方法があります。Cで記述されたコードでrubyを拡張できます。SWIGを参照してください。

または、ルビーを埋め込むことができます。ここここここを参照してください。

ところで、あなたはルビーを「拡張」するのではなく、ルビーを「埋め込む」と言っていますか。

于 2010-05-10T09:43:07.930 に答える