Domanda

Sto scrivendo un'app che chiama il codice Ruby da c.Ho qualche difficoltà e mi chiedevo se qualcuno potesse indicarmi la direzione del rito.

Attualmente ho nel mio C.

#include ruby.h

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

Il mio file ruby ​​si trova nella stessa directory del mio file c e si chiama myRubyFile.rb e contiene una definizione della funzione RubyFunction().

Questa è una riduzione di ciò che in realtà voglio fare, rendendolo solo più leggibile per gli altri.Ho solo bisogno di un feedback sul fatto che questo sia il metodo corretto per chiamare il codice Ruby dal mio file c.

Saluti

È stato utile?

Soluzione

Risposta breve:

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);

Risposta più lunga:

Il primo argomento a rb_funcall è il ricevitore della chiamata al metodo.

Supponendo te defined RubyFunction() al di fuori di qualsiasi classe esplicita o contesto di modulo, viene aggiunto all'autoclasse dell'implicito, oggetto principale al "livello più alto" di ogni rubino vm.

In Ruby, questo oggetto è accessibile come livello superiore 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

In C sotto 1.9 è accessibile come indicato sopra.

Altri suggerimenti

cerco di utilizzare il seguente approccio:

struct base ai dati di condivisione

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

creare una funzione per gli oggetti di chiamata rubino su qualche parte del codice

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);
}

In alcune parti del codice ...

    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";

E 'sempre una buona idea di avvolgere rb_funcall con rb_protect.

Un'altra cosa interessante è quello di conoscere i parametri della richiamata, un approccio è il seguente

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);

non mi piace chiamare rubino da dentro C a meno che non si dispone di progetto complesso C, che non si vuole ricostruire in Ruby.

Ci sono due modi per interagire tra C e rubino. È possibile estendere rubino con codice scritto in C. See SWIG .

In alternativa, è possibile incorporare rubino, vedi qui , qui e qui .

A proposito, che cosa si parla è "incorporare" ruby, non "estendere" ruby.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top