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是方法调用的接收者

假设您在任何显式类或模块上下文之外,则将其添加到每个 ruby​​ vm 的“顶级”的隐式def对象的特征类中RubyFunction()

在 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

在 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_protect 包装 rb_funcall 总是一个好主意。

另一个有趣的事情是知道回调的参数,一种方法如下

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 内部调用 ruby​​,除非您有复杂的 C 项目,并且不想在 ruby​​ 中重新构建。

C 和 ruby​​ 之间有两种交互方式。您可以使用用 C 编写的代码扩展 ruby​​。请参阅SWIG

或者您可以嵌入 ruby​​,请参见此处此处此处

顺便说一句,你提到的是“嵌入”红宝石,而不是“扩展”红宝石。

于 2010-05-10T09:43:07.930 回答