My ruby based data analysis project needs high performance. I plan to create an inline C function that reads a piece of data and updates some global variables, which I can do more processing in ruby.
The following toy code:
require 'inline'
class Foo
inline :C do |builder|
builder.c_raw_singleton <<SRC
static char *cstr = "hi you'all, welcome";
void write_global(VALUE self, VALUE *name){
rb_gv_set(rb_string_value_cstr(name), rb_str_new_cstr(cstr));
cstr[1] ++;
}
SRC
end
end
$bar = ""
Foo.write_global('bar') #=> 1
puts $bar;
Foo.write_global('bar') #=> 1
puts $bar;
will cause exception on ruby interpreter.
I wonder what the problem is.
UPDATE 1
Thanks to @mu-is-too-short who pointed out the constant string can't be modified, I changed it to be a buffer (see the following), but got compile errors like
WARNING: '&cstr[0]' not understood
WARNING: '"%s"' not understood
WARNING: '"hi you'all' not understood
WARNING: 'welcome"' not understood
WARNING: Can't find signature in "\t static char cstr[20];static int f(&cstr[0], \"%s\", \"hi you'all, welcome\");\n void write_global(VALUE self, VALUE *name){\n rb_gv_set(rb_string_value_cstr(name), rb_str_new_cstr(cstr));\n\t\tcstr[1] ++;\n }\n"
inline1a.rb:5:37: error: expected declaration specifiers or ‘...’ before ‘&’ token
builder.c_raw_singleton <<SRC
Here is the new code that doesn't try to modify constant string.
require 'inline'
class Foo
inline :C do |builder|
builder.c_raw_singleton <<SRC
static char cstr[20];
sprintf(&cstr[0], "%s", "hi you'all, welcome");
void write_global(VALUE self, VALUE *name){
rb_gv_set(rb_string_value_cstr(name), rb_str_new_cstr(cstr));
cstr[1] ++;
}
SRC
end
end
$bar = ""
Foo.write_global('bar') #=> 1
puts $bar;
Foo.write_global('bar') #=> 1
puts $bar;