代码之家  ›  专栏  ›  技术社区  ›  Robert Rouse

从C++调用Ruby类方法

  •  5
  • Robert Rouse  · 技术社区  · 16 年前

    rb_实习生我可以想办法让它工作,但我什么都没有得到。

    示例类

    class CallTest
       def go
        (do something here)
       end
    end
    

    尝试在C++中调用:

    rb_funcall(?, rb_intern("go"), 0);

    盒子里装的是什么?空间我知道如果我在那里使用Qnil,它会调用

    我走错方向了吗?

    另外,如果需要的话,我不想提前知道类名 通过名称将其传递给我的应用程序。

    我正在使用SWIG生成绑定。

    2 回复  |  直到 16 年前
        1
  •  7
  •   rampion    16 年前

    首先, go 正如您所定义的,它不是一个类方法,而是一个 .

    作为一种面向对象的语言,所有ruby方法都需要一个接收者,即调用该方法的对象。对于实例方法,接收方是类的实例,对于类方法,接收方是类对象本身。

    这个您拥有的占位符是方法调用接收器的插槽。

    rb_funcall(a_CallTest_instance, rb_intern("go"), 0);
    

    哪里 a_CallTest_instance 是您使用创建的CallTest的实例 rb_class_new_instance() .

    如果将其设置为类方法:

    class CallTest
      def self.go
        # ...
      end
    end
    

    那么你需要使用 CallTest

    rb_funcall(klass, rb_intern("go"), 0);
    

    您可以获得对 呼叫测试 rb_const_get()

    VALUE klass = rb_const_get(rb_cObject, rb_intern('CallTest'));
    

    使用 rb_cObject 呼叫测试 是在全局上下文中定义的。

        2
  •  3
  •   Gosh    15 年前

    我也用SWIG。这些特定的示例文件应该对您有所帮助。

    1) test.rb

    require 'test.so'
    class A
        def func1(buffer)
            puts "ruby instance method: #{buffer}"
        end
    end
    def func2(buffer)
        puts "ruby global method: #{buffer}"
    end
    module Z
        def Z.func3(buffer)
            puts "ruby module method: #{buffer}"
        end
    end
    
    a = A.new
    t = Test::Test1.new()
    t.call(a, "func1", "Hello", 5)
    t.call(method(:func2), "func2", "Yabaaa", 6)
    t.call(Z, "func3", "Yahooooooo", 10)
    

    2) 测试h:

    #include <ruby.h>
    class Test1
    {
    public:
        void call(VALUE obj, char* func_name, const char* buffer, int size)
        {
            VALUE val = rb_str_new(buffer, size);   
            rb_funcall(obj, rb_intern(func_name), 1, val);
        }
    };
    

    3) 测试一:

    %module test
    
    %{
    #include "test.h"
    %}
    
    %exception
    {
        try
        {
            $action
        }
        catch (std::exception& ex)
        {
            static VALUE cpperror = rb_define_class("test Exception", rb_eStandardError);
            rb_raise(cpperror, ex.what());
        }
        catch (...)
        {
            static VALUE cpperror = rb_define_class("test UnknownException", rb_eStandardError);
            rb_raise(cpperror, "Unknown catched");
        }
    }
    
    %include "test.h"
    

    ruby ./test.rb 
    ruby instance method: Hello
    ruby global method: Yabaaa
    ruby module method: Yahooooooo