У меня есть приложение Rails, которое должно показать результаты симулятора Monte Carlo, и в первый раз Ruby просто не достаточно быстро для моих нужд. Итак, я начал копаться, чтобы посмотреть, могу ли я переписать мою симуляцию на C и использовать эти результаты в Ruby, а некоторые googling превратили RubyInline gem, чтобы легко писать более быстрый код C непосредственно в Ruby. Делая простые вещи отлично работает, например, некоторые основные функции написаны на Ruby, и C:Создание C структур с использованием RubyInline gem
class FasterFunctions
inline do |builder|
builder.c '
double rand_sum(int trials)
{
double sum = 0.0;
for (int i = 0; i<trials; i++)
{
sum += (double)rand()/(double)RAND_MAX;
}
return sum;
}'
builder.c '
long loop_sum(long trials)
{
long sum = 0;
for (long i = 0; i<trials; i++)
{
sum+=i;
}
return sum;
}'
end
end
#the C version is 4 orders of magnitude faster
trials = 1_000_000
ruby_sum = 0
trials.times {|i| ruby_sum += i}
c_sum = FasterRand.new.loop_sum(trials)
# the C version is 1 order of magnitude faster
ruby_sum = 0.0
trials.times {ruby_sum += rand}
c_sum = FasterRand.new.rand_sum(trials)
Так, большой, он должен определенно ускорить мой сим, так как это в значительной степени просто генерации случайных чисел и добавление материала на основе по этим результатам. К сожалению, помимо основных вещей, подобных этому, я не могу понять, как писать свою программу. Мне нужно передать некоторые структуры, чтобы действовать как переменные состояния, поэтому в первом порядке бизнеса выясняется, как создать структуру C. Чтение the documentation, похоже, должно быть довольно простым.
accessor(method, type, member = method)
Adds a reader and writer for a C struct member wrapped via Data_Wrap_Struct. method is the ruby name to give the accessor, type is the C type. Unless the C member name is overridden with member, the method name is used as the struct member.
builder.struct_name = 'MyStruct' builder.accessor :title, 'char *' builder.accessor :stream_index, 'int', :index
документация не совсем ясно для меня, но я предполагаю, что я положил, что в классе много, как раньше, и сделать что-то вроде следующего, чтобы получить доступ к нему:
class MyStructClass
inline do |builder|
builder.struct_name = 'MyStruct'
builder.accessor :title, 'char *'
builder.accessor :stream_index, 'int', :index
end
end
#possible this
struct = MyStructClass.new.MyStruct
struct.title = 'A Title'
#or maybe
struct = MyStructClass.new
struct.title = 'A Title'
К сожалению , я даже не могу получить, что далеко
*/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:456:3: error: use of undeclared identifier 'MyStruct' MyStruct *pointer; ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:456:13: error: use of undeclared identifier 'pointer' MyStruct *pointer; ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:458:35: error: use of undeclared identifier 'pointer' Data_Get_Struct(self, MyStruct, pointer); ^ /.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/ruby.h:1038:6: note: expanded from macro 'Data_Get_Struct' (sval) = (type)DATA_PTR(obj);\ ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:458:25: error: use of undeclared identifier 'MyStruct' Data_Get_Struct(self, MyStruct, pointer); ^ /.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/ruby.h:1038:15: note: expanded from macro 'Data_Get_Struct' (sval) = (type)DATA_PTR(obj);\ ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:458:3: error: expected expression Data_Get_Struct(self, MyStruct, pointer); ^ /.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/ruby.h:1038:20: note: expanded from macro 'Data_Get_Struct' (sval) = (type)DATA_PTR(obj);\ ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:460:23: error: use of undeclared identifier 'pointer' return (rb_str_new2(pointer->title)); ^ */.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/intern.h:786:27: note: expanded from macro 'rb_str_new_cstr' (__builtin_constant_p(str)) ? \ ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:460:23: error: use of undeclared identifier 'pointer' */.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/intern.h:787:14: note: expanded from macro 'rb_str_new_cstr' rb_str_new((str), (long)strlen(str)) : \ ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:460:23: error: use of undeclared identifier 'pointer' */.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/intern.h:787:33: note: expanded from macro 'rb_str_new_cstr' rb_str_new((str), (long)strlen(str)) : \ ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:460:23: error: use of undeclared identifier 'pointer' */.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/intern.h:788:18: note: expanded from macro 'rb_str_new_cstr' rb_str_new_cstr(str); \ ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:460:10: error: returning 'void' from a function with incompatible result type 'VALUE' (aka 'unsigned long') return (rb_str_new2(pointer->title)); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:478:3: error: use of undeclared identifier 'MyStruct' MyStruct *pointer; ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:478:13: error: use of undeclared identifier 'pointer' MyStruct *pointer; ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:480:35: error: use of undeclared identifier 'pointer' Data_Get_Struct(self, MyStruct, pointer); ^ /.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/ruby.h:1038:6: note: expanded from macro 'Data_Get_Struct' (sval) = (type)DATA_PTR(obj);\ ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:480:25: error: use of undeclared identifier 'MyStruct' Data_Get_Struct(self, MyStruct, pointer); ^ /.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/ruby.h:1038:15: note: expanded from macro 'Data_Get_Struct' (sval) = (type)DATA_PTR(obj);\ ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:480:3: error: expected expression Data_Get_Struct(self, MyStruct, pointer); ^ /.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/ruby.h:1038:20: note: expanded from macro 'Data_Get_Struct' (sval) = (type)DATA_PTR(obj);\ ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:482:3: error: use of undeclared identifier 'pointer' pointer->title = StringValuePtr(value); ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:456:3: error: use of undeclared identifier 'MyStruct' MyStruct *pointer; ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:456:13: error: use of undeclared identifier 'pointer' MyStruct *pointer; ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:458:35: error: use of undeclared identifier 'pointer' Data_Get_Struct(self, MyStruct, pointer); ^ /.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/ruby.h:1038:6: note: expanded from macro 'Data_Get_Struct' (sval) = (type)DATA_PTR(obj);\ ^fatal error: too many errors emitted, stopping now [-ferror-limit=]
Я сделал кучу прибегая к помощи, но в значительной степени каждый примере я нашел дело только с простым прецедентом я обрисовал в первом. Первая ошибка это выплюнуть, что MyStruct была необъявленная, поэтому я попытался добавить определение структуры до методов доступа, например, так:
builder.c '
typedef struct
{
char *title;
int index;
} MyStruct;
'
Это ничего не делать, а документация представляется очевидным, что c метод предназначен только для объявления функций, а не для структур. Я не совсем уверен, что делать дальше, есть ли у кого-нибудь еще опыт?