ruby - 如何将上下文传递给 C/C++ 中定义的 Ruby 方法

标签 ruby wrapper

我目前正在编写一组到 Ruby 解释器的 API 绑定(bind)。问题在于绑定(bind)定义不是静态的并且在初始化时检索。我可以轻松地动态创建类型,但为了添加方法,我需要静态处理程序:

static VALUE dispatchInstanceMethod( int argc, VALUE *argv, VALUE obj )
{...}

static VALUE dispatchClassMethod( int argc, VALUE *argv, VALUE obj )
{...}

VALUE cls  = rb_define_class_id_under( myModule, nameID, rb_cObject );
rb_define_method( cls, "methodName", RUBY_METHOD_FUNC(dispatchInstanceMethod), -1 );
rb_define_singleton_method( cls, "methodName", RUBY_METHOD_FUNC(dispatchClassMethod), -1 );

但是,这要求每个方法(静态方法和实例方法)使用不同的处理程序。 由于我是在运行时生成这些定义,因此我必须使用通用调度程序来 处理所有方法调用。但是,我的调度程序不知道哪个方法和哪个类 被称为。我如何检索该信息?可以检索类(class)信息 来自传递给处理程序的 self 对象,但在静态方法的情况下,self 是 自行键入。我可以将任何类型的用户数据附加到类类型 VALUE 吗?我怎么知道 如果每个方法都使用相同的调度程序函数,则调用哪个 Ruby 方法?

我过去合作过的其他一些口译员提供了 此类数据的通用 void* 指针(通常与释放函数一起),或其他一些机制,但 Ruby 中似乎没有类似的东西。我是否错过了它,或者这种用途根本不可用?

最佳答案

这更具实验性。我不确定这到底是如何工作的,但它基于 Ruby 的 define_method用于在运行时定义正确的方法

VALUE context; // context for method call

VALUE dispatchInstanceMethod(VALUE first_arg, VALUE context, int argc, VALUE* argv)
{
    // first_arg is the first arg passed to your method, probably shouldn't use it
    // just use argc, argv instead for accessing all args
    // context should(?) be what we passed at the time of definition
}

void dynamically_create_class()
{
    VALUE cls = rb_define_class_id_under(myModule, nameID, rb_cObject);
    ID define_method = rb_intern("define_method");

    VALUE name = // method name as a Symbol object e.g. using ID2SYM
    context = // set to whatever context we need for the call
    rb_global_variable(context); // don't garbage-collect it
    rb_block_call(cls, define_method, 1, &name, dispatchInstanceMethod, context);
}

要使其发挥作用(如果可以的话),您需要为每个方法定义使用不同的 context 变量。这些变量的生命周期必须超过类的生命周期,因此它们需要在某个地方全局可用。这就是稍后当每个方法实际调用 dispatchInstanceMethod 时如何区分它的方法。

关于ruby - 如何将上下文传递给 C/C++ 中定义的 Ruby 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58824329/

相关文章:

ruby - 在容器中运行 selenium/capybara 测试时出现 Docker "Failed to open TCP connection to 127.0.0.1:4444"

ruby - 如何从参数数组中检索 Ruby/Sinatra 参数?

html - 网站跨越整个页面,我不希望它

ruby - 大写方法不返回大写字符串

ruby - 为什么在 Ruby 图形库 (RGL) 中生成点文件而不是 jpg 文件?

ruby-on-rails - Rails Controller 私有(private)方法的功能测试

java - 包装类的声明

c++ - 在 boost::python 的类中公开公共(public)结构

用于 C++ 的 C# 包装器,但仅编译为静态库

java - Google 搜索是否为应用程序提供 API?