Embedding Rubin, den Aufruf einer Funktion von C
-
25-09-2019 - |
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
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.
Oder Sie Rubin einbetten können, finden Sie hier: hier und hier .
BTW, was Sie erwähnen, ist "einbetten" Rubin, nicht "verlängern" Rubin.