Frage

Ich schreibe eine app, dass Anrufe Code von c Rubin. Ich bin ein wenig Schwierigkeiten haben, und fragte sich, ob jemand mich in die rite Richtung zeigen könnte.

ich derzeit in meiner C haben.

#include ruby.h

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

Meine Rubin-Datei im selben Verzeichnis wie meine c-Datei und heißt myRubyFile.rb und enthält eine Definition der Funktion RubyFunction ().

Dies ist ein Schnitt nach unten, was ich will eigentlich tun, nur machen es besser lesbar für andere. Ich brauche nur ein Feedback darüber, ob dies die richtige Methode zum Aufruf Ruby-Code aus meiner C-Datei.

Viele Grüße

War es hilfreich?

Lösung

Kurze Antwort:

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

Lange Antwort:

Das erste Argument für rb_funcall ist die Empfänger des Methodenaufrufes.

Angenommen, Sie def ausserhalb jeglicher expliziten Klasse oder des Moduls Kontext RubyFunction()ined, so wird es hinzugefügt, um die Eigenklasse des impliziten, Hauptobjekt auf der „Top-Level“ jeder Rubin vm .

In Rubin, dieses Objekt zugegriffen werden, wie die Top-Level-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 unter 1,9 zugänglich ist, wie oben angegeben.

Andere Tipps

Ich versuche, den folgenden Ansatz zu verwenden:

Basis-Struktur zu teilen Daten

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

Erstellen Sie eine Funktion für den Anruf Rubin Objekte auf einem Teil des Codes

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

Auf einem Teil des Codes ...

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

ist immer eine gute Idee zu wickeln rb_funcall mit rb_protect.

Eine weitere interessante Sache ist, die Parameter des Rückrufs zu wissen, ein Ansatz ist die folgende

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

Ich weiß nicht, wie zu Anruf rubin von innen C, wenn Sie komplexes C-Projekt haben, die Sie nicht wollen, zu re-build in Ruby.

gibt es zwei Möglichkeiten von C und Rubin zu interagieren. Sie können mit dem Code geschrieben in C. Siehe erweitern Rubin SWIG .

Oder Sie Rubin einbetten können, finden Sie hier: hier und hier .

BTW, was Sie erwähnen, ist "einbetten" Rubin, nicht "verlängern" Rubin.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top