arr=Array.new(3)
arr[0]=5
arr[1]=3
arr[2]=2
这些行应该调用此函数,https://github.com/ruby/ruby/blob/trunk/array.c#L568据此,http://www.ruby-doc.org/core-1.9.3/Array.html
所以我在那里添加了几行来显示数组的值。但我没有得到预期的结果。
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);
}
}
我得到的结果是这样的:
arr=Array.new(3)
arr[0]=5
arr[1]=3
arr[2]=2
r: 9
r: 9
r: 9
为什么会出现这样的结果呢?为什么是 9?
我按照以下方法解决了这个问题:
- How to convert ruby array to C array with RubyInline?
- https://github.com/ruby/ruby/blob/trunk/README.EXT#L131
- https://github.com/ruby/ruby/blob/trunk/include/ruby/ruby.h#L708
- https://github.com/ruby/ruby/blob/trunk/include/ruby/ruby.h#L731
任何人都可以帮忙在 C 中显示/打印 Ruby 数组的值吗?
最佳答案
这没有任何意义:
result = LONG2NUM(s_arr[i]);
LONG2NUM
用于将 C long int
转换为保存数字的 Ruby VALUE
; s_arr[i]
已经是 VALUE
,因此您可以有效执行 VALUE v = LONG2NUM((VALUE)5)
等操作。 LONG2NUM
在 ruby.h
中定义为以下内容的包装器:
#define LONG2NUM_internal(v) (FIXABLE(v) ? LONG2FIX(v) : rb_int2big(v))
如果v
适合VALUE
而不将其转换为bignum,那么你最终会使用这个:
#define INT2FIX(i) ((VALUE)(((SIGNED_VALUE)(i))<<1 | FIXNUM_FLAG))
因此,您基本上是在对指针进行一系列位争论,并想知道为什么它总是显示 9
;认为自己幸运(或不幸),它没有说段错误。
您想要将保存数字的 VALUE
转换为 C 整数。您可能想使用FIX2LONG
:
#define FIX2LONG(x) (long)RSHIFT((SIGNED_VALUE)(x),1)
或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
所以像这样:
long result;
for(i = 0; i < len; i++) {
result = NUM2LONG(s_arr[i]);
printf("r: %ld\n", result);
}
请注意切换到 %ld
,因为我们现在使用 long
,并且我们总是打开所有提示 printf< 不匹配的挑剔编译器标志
格式和参数。当然,这假设您确定该数组包含适合 C long
的数字。
关于c - 如何在 C 中访问 ruby 数组的值? (编辑 array.c :rb_ary_initialize from ruby source code),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11161975/