MST

星途 面试题库

面试题:Ruby与C扩展交互中的数据类型处理

在Ruby与C扩展交互开发中,Ruby的数组如何传递给C函数并在C函数中正确处理?如果C函数处理完后要将修改后的数组返回给Ruby,又该如何实现?请详细描述实现思路和关键代码。
50.2万 热度难度
编程语言Ruby

知识考点

AI 面试

面试题答案

一键面试

1. Ruby数组传递给C函数

  1. 实现思路
    • 在Ruby中,数组是一个对象。通过Ruby的C API,可以获取数组对象的指针,然后遍历数组元素,根据元素类型进行相应处理。
    • 利用rb_ary_entry函数可以获取数组指定索引位置的元素。
  2. 关键代码
#include "ruby.h"

// 定义一个C函数,接收Ruby数组
VALUE my_function(VALUE ary) {
    long len = RARRAY_LEN(ary);
    for (long i = 0; i < len; i++) {
        VALUE element = rb_ary_entry(ary, i);
        // 这里可以根据element的类型进行相应处理,例如:
        if (TYPE(element) == T_FIXNUM) {
            long num = FIX2LONG(element);
            // 对num进行处理
        }
    }
    return Qnil;
}

在Ruby中注册这个函数:

require "rbconfig"
require "mkmf"

create_makefile('my_ext')
// extconf.c
#include "ruby.h"

void Init_my_ext() {
    VALUE m = rb_define_module("MyExt");
    rb_define_module_function(m, "my_function", my_function, 1);
}

2. C函数将修改后的数组返回给Ruby

  1. 实现思路
    • 在C函数中创建一个新的Ruby数组对象。
    • 将处理后的元素逐个添加到新数组中。
    • 最后返回这个新数组对象给Ruby。
  2. 关键代码
#include "ruby.h"

// 定义一个C函数,接收Ruby数组并返回修改后的数组
VALUE my_function(VALUE ary) {
    long len = RARRAY_LEN(ary);
    VALUE new_ary = rb_ary_new();
    for (long i = 0; i < len; i++) {
        VALUE element = rb_ary_entry(ary, i);
        // 对element进行处理,例如翻倍
        if (TYPE(element) == T_FIXNUM) {
            long num = FIX2LONG(element);
            num = num * 2;
            VALUE new_element = LONG2FIX(num);
            rb_ary_push(new_ary, new_element);
        }
    }
    return new_ary;
}

同样在Ruby中注册这个函数:

require "rbconfig"
require "mkmf"

create_makefile('my_ext')
// extconf.c
#include "ruby.h"

void Init_my_ext() {
    VALUE m = rb_define_module("MyExt");
    rb_define_module_function(m, "my_function", my_function, 1);
}

在Ruby中调用:

require 'my_ext'
ary = [1, 2, 3]
result = MyExt.my_function(ary)
puts result.inspect