Hi,
I hope someone can help me.
I’m trying to write some C extensions with
the main objective of speeding up some tasks in Ruby.
I’m relying on the README.ext file as well as
in Chapter 17 of the ‘Prog. Ruby’ book from
Thomas and Hunt.
The question is about creating a global variable
in C and see it in Ruby. This is documented
in both those documents, but has a strange behavior
when implementing. Perhaps I’m missing something.
Here is the script I tried both with Ruby 1.8.0/2003-03-31
version and Ruby 1.6.8. The results are
slightly different. I made a lot of experiments with the code below
in the last few days and looked at the
ruby sources (also the sources in extension modules)
but I didn’t see anything that could help me.
The fact that the code runs differently in
1.6.8 and 1.8.0 appears to indicate some kind
of different behavior. The script is:
···
require ‘inline’ # use Inline module
class Fake
inline_c_raw %q[
static VALUE newvar(int argc, VALUE *argv, VALUE self) {
VALUE temp;
temp = rb_ary_new();
rb_ary_push(temp, rb_float_new(3.3));
rb_define_variable("$tempor", &temp);
rb_global_variable(&temp);
return Qnil;
}
]
end
f = Fake.new()
f.newvar() # calls newvar
puts "\n"
puts $tempor.class
puts $tempor[0]
puts ""
puts self.id
#puts global_variables.grep(/tem/)
puts "\n"
puts $tempor.class
puts $tempor[0]
puts ""
puts self.id
The C code created by the inline module is
#include “ruby.h”
static VALUE newvar(int argc, VALUE *argv, VALUE self) {
VALUE temp;
temp = rb_ary_new();
rb_ary_push(temp, rb_float_new(3.3));
rb_define_variable("$tempor", &temp);
rb_global_variable(&temp);
return Qnil;
}
VALUE cMod_Fake_newvar;
void Init_Mod_Fake_newvar() {
cMod_Fake_newvar = rb_define_module(“Mod_Fake_newvar”);
rb_define_method(cMod_Fake_newvar, “newvar”, newvar, -1);
}
The result of running ruby-1.8.0 is the following
[jasa@localhost rb]$ ruby z.rb
Fixnum
0
537799894
z.rb:37: [BUG] Segmentation fault
ruby 1.8.0 (2003-03-31) [i686-linux-gnu]
Aborted
That is, the first time the class and value of $tempor are wrong.
The second time, the examination of $tempor crashes Ruby.
However, the variable is supposedelly global,
and it is ‘declared’ to Garbage Collection mechanism
with rb_global_variable(&temp).
The segmentation fault appears to be related with GC.
More strangely, if the line
’#puts global_variables.grep(/tem/)'
is uncommented, there is no segmentation fault
although $tempor is still a Fixnum instead of an Array.
Here is the result:
[jasa@localhost rb]$ ruby z.rb
Fixnum
0
537799894
$tempor
Fixnum
1
537799894
But with Ruby1.6.8 (24-12-2002) the segmentation
fault above never occurs, which means it is insensible
to the line "puts global_variables.grep(/tem/)"
being commented or not. However, the Fixnum
instead of Array class of $tempor is still wrong
with ruby 1.6.8…
What am I overlooking here? Are there some extra
’declarations’ I shall do to keep the variable global?
(I didn’t found much help in the Ruby sources
and in sources of extensions…
Thanks in advance!
Jose Augusto