سؤال

أنا أكتب تطبيقًا يستدعي رمز روبي من 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 هل المتلقي من طريقة الدعوة.

على افتراض أنك defined 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. انظر جرعة كبيرة.

أو يمكنك تضمين روبي ، انظر هنا, هنا و هنا.

راجع للشغل ، ماذا تذكر هو "تضمين" روبي ، وليس "تمديد" روبي.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top