代码之家  ›  专栏  ›  技术社区  ›  Lloyd Powell binku

嵌入Ruby,从C调用函数

  •  4
  • Lloyd Powell binku  · 技术社区  · 15 年前

    我正在编写一个从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代码的正确方法的反馈。

    当做

    3 回复  |  直到 15 年前
        1
  •  6
  •   pilcrow    15 年前

    简短回答:

    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 接受者 方法调用的。

    假设你 def 沉醉的 RubyFunction() 在任何显式类或模块上下文之外,然后将其添加到隐式的特征类中, 每个RubyVM的“顶层”的主对象 .

    在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中,可按上述说明进入。

        2
  •  0
  •   camp0    9 年前

    我尝试使用以下方法:

    共享数据的基本结构

    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 U保护包装RB U 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);
    
        3
  •  -2
  •   Community CDub    7 年前

    我不喜欢从C内部调用Ruby,除非您有复杂的C项目,而您不想在Ruby中重新构建它。

    C和Ruby之间有两种交互方式。您可以使用C语言编写的代码扩展Ruby。 SWIG .

    或者你可以嵌入红宝石,看 here , here here .

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