質問

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 コードを呼び出す正しい方法であるかどうかについてフィードバックが必要です。

よろしく

役に立ちましたか?

解決

答え:

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受信機 の方法。

とい defined RubyFunction() 外の明示的なクラスやモジュールの文脈で、その後追加されますのeigenclassの暗黙, 主なオブジェクトの"トップレベル"の毎ruby vm.

Rubyで、このオブジェクトにアクセスしてトップレベルの 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

C下1.9アクセス可能ですと答させていただきます。

他のヒント

私は、次のアプローチを使用してみます:

共有データへの基本的な構造体

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

あなたのコードの一部にコールルビー・オブジェクトの関数を作成します。

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_protectでrb_funcallラップすることは常に良い考えです。

もう一つの興味深い点は、コールバックのパラメータを知っている、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);

Ruby で再構築したくない複雑な C プロジェクトがある場合を除き、C 内から Ruby を呼び出すことは好きではありません。

C と Ruby の間で対話するには 2 つの方法があります。C で書かれたコードを使用して Ruby を拡張できます。見る スイグ.

または、Ruby を埋め込むこともできます。 ここ, ここ そして ここ.

ところで、あなたが言及しているのは、Rubyを「埋め込む」ことであり、Rubyを「拡張する」ことではありません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top