تضمين روبي، واستدعاء دالة من C
-
25-09-2019 - |
سؤال
أنا أكتب تطبيقًا يستدعي رمز روبي من c.أواجه صعوبة صغيرة وأتساءل عما إذا كان بإمكان أي شخص أن يوجهني في اتجاه الطقوس.
لدي حاليًا في C.
#include ruby.h
main()
{
ruby_init();
rb_require("myRubyFile");
rb_funcall(rb_module_new(), rb_intern("RubyFunction"), 0, NULL);
}
يوجد ملف روبي الخاص بي في نفس الدليل الموجود فيه ملف c الخاص بي ويسمى myRubyFile.rb ويحتوي على تعريف للوظيفة RubyFunction().
هذا اختصار لما أريد فعله بالفعل، فقط لجعله أكثر قابلية للقراءة للآخرين.أنا فقط بحاجة إلى بعض التعليقات حول ما إذا كانت هذه هي الطريقة الصحيحة لاستدعاء رمز روبي من ملف c الخاص بي.
يعتبر
المحلول
اجابة قصيرة:
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
ined RubyFunction()
خارج أي فئة صريحة أو سياق الوحدة النمطية، ثم تتم إضافتها إلى الفئة الذاتية الضمنية، الكائن الرئيسي في "المستوى الأعلى" لكل روبي vm.
في روبي، يمكن الوصول إلى هذا الكائن باعتباره المستوى الأعلى 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 أقل من 1.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_funcall مع rb_protect.
شيء آخر مثير للاهتمام هو معرفة معايير رد الاتصال ، نهج واحد هو ما يلي
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);
لا أحب الاتصال بـ Ruby من Inside C إلا إذا كان لديك مشروع C المعقد الذي لا تريد إعادة بناءه في Ruby.
هناك طريقتان للتفاعل بين C و Ruby. يمكنك تمديد روبي مع رمز مكتوب في C. انظر جرعة كبيرة.
أو يمكنك تضمين روبي ، انظر هنا, هنا و هنا.
راجع للشغل ، ماذا تذكر هو "تضمين" روبي ، وليس "تمديد" روبي.