简体   繁体   English

如何在C中访问ruby数组的值? (从ruby源代码编辑array.c:rb_ary_initialize)

[英]How can i access the value of a ruby array in C? (editing array.c:rb_ary_initialize from ruby source code)

arr=Array.new(3)
arr[0]=5
arr[1]=3
arr[2]=2

These lines should call this function, https://github.com/ruby/ruby/blob/trunk/array.c#L568 according to this, http://www.ruby-doc.org/core-1.9.3/Array.html 这些行应根据http://www.ruby-doc.org/core-1.9.3/来调用此函数https://github.com/ruby/ruby/blob/trunk/array.c#L568 Array.html

So I have added couple of lines there to display the values of array. 因此,我在其中添加了几行以显示数组的值。 But i didn't get the expected result. 但是我没有得到预期的结果。

else {
    memfill(RARRAY_PTR(ary), len, val);
    ARY_SET_LEN(ary, len);
    int i;
    int result;
    result = 0;
    VALUE *s_arr = RARRAY_PTR(ary);
    for(i = 0; i < len; i++) {
        result = LONG2NUM(s_arr[i]);
        printf("r: %d\n",result);
    }
}

I got the result like this: 我得到这样的结果:

arr=Array.new(3)
arr[0]=5
arr[1]=3
arr[2]=2
r: 9
r: 9
r: 9

Why is this result? 为什么会这样呢? Why 9? 为什么是9?

I have followed these to solve it: 我已经遵循这些来解决它:

Can anyone please help to display/printf the value of Ruby array in C? 谁能帮助显示/打印C语言中Ruby数组的值?

This doesn't make any sense: 这没有任何意义:

result = LONG2NUM(s_arr[i]);

LONG2NUM is used to convert a C long int to a Ruby VALUE that holds a number; LONG2NUM用于将C long int转换为包含数字的Ruby VALUE s_arr[i] is already a VALUE so you're effectively doing things like VALUE v = LONG2NUM((VALUE)5) . s_arr[i]已经是一个VALUE因此您实际上正在执行VALUE v = LONG2NUM((VALUE)5)类的事情。 LONG2NUM is defined in ruby.h as a wrapper for this: ruby.h LONG2NUM定义为此:

#define LONG2NUM_internal(v) (FIXABLE(v) ? LONG2FIX(v) : rb_int2big(v))

and if v fits in a VALUE without converting it to a bignum, then you end up using this: 如果v符合VALUE而不将其转换为大数,那么您最终将使用以下代码:

#define INT2FIX(i) ((VALUE)(((SIGNED_VALUE)(i))<<1 | FIXNUM_FLAG))

So you're basically doing a bunch of bit wrangling on a pointer and wondering why it always says 9 ; 所以您基本上是在指针上进行一堆争吵,想知道为什么它总是说9 ; consider yourself lucky (or unlucky) that it doesn't say segmentation fault . 认为自己很幸运(或不幸运)并没有表示细分错误

You want to convert a VALUE which holds a number to a C integer. 您想要将包含数字的VALUE转换为C整数。 You probably want to use FIX2LONG : 您可能要使用FIX2LONG

#define FIX2LONG(x) (long)RSHIFT((SIGNED_VALUE)(x),1)

or NUM2LONG : NUM2LONG

#define NUM2LONG_internal(x) ((long)(FIXNUM_P(x) ? FIX2LONG(x) : rb_num2long(x)))
#ifdef __GNUC__
#define NUM2LONG(x) \
    __extension__ ({VALUE num2long_x = (x); NUM2LONG_internal(num2long_x);})
#else
static inline long
NUM2LONG(VALUE x)
{
    return NUM2LONG_internal(x);
}
#endif

So something like this: 所以像这样:

long result;
for(i = 0; i < len; i++) {
    result = NUM2LONG(s_arr[i]);
    printf("r: %ld\n", result);
}

Note the switch to %ld since we're using long s now and we always turn on all the picky compiler flags that complain about mismatched printf formats and arguments. 注意,因为我们现在使用long s,所以切换到%ld并且我们总是打开所有挑剔的编译器标志,这些标志抱怨printf格式和参数不匹配。 Of course, this assumes that you are certain that the array contains numbers that will fit in a C long . 当然,这假定您确定数组包含适合C long

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM